home *** CD-ROM | disk | FTP | other *** search
/ Network Supervisor's Toolkit / Network Supervisor's Toolkit.iso / tools / nwtp06 / nwfile.pas < prev    next >
Pascal/Delphi Source File  |  1996-07-10  |  92KB  |  2,999 lines

  1. {$X+,B-,V-} {essential compiler directives}
  2.  
  3. Unit nwFile;
  4.  
  5. { nwFile unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk }
  6.  
  7. INTERFACE
  8. { Primary Functions                     Interrupt: comments:
  9.  
  10. Volume Management (Volume Tables)
  11. ---------------------------------
  12.  
  13. * ClearObjectVolRestriction             (F216/22)  (3) [aka ClearVolumeRestrictions/RemoveObjectDiskRestrictions]
  14. * GetObjectVolRestriction               (F216/29)  (3) [aka GetObjDiskRestrictions/GetObjectDiskUsageAndRestrictions]
  15. * GetVolumeName                         (F216/06)
  16. * GetVolumeNameWithHandle               (F216/15)      [aka GetVolumeInfoWithHandle]
  17. * GetVolumeNumber                       (F216/05)
  18. * GetVolumeUsage                        (F216/2C)  (3) [aka GetExtendedVolumeInformation]
  19. * IsVolumeRemovable                     (F212)         [aka GetVolumeInfoWithNumber]
  20. * ScanVolForRestrictions                (F216/20)  (3)
  21. * SetObjectVolRestriction               (F216/21)  (3) [aka SetVolumeRestrictions/SetObjectVolSpaceLimit
  22.                                                             /AddUserDiskspaceRestriction]
  23.  
  24. Directory Handles (Directory Handle Table/Drive tables)
  25. -------------------------------------------------------
  26.  
  27. * AllocPermanentDirHandle               (F216/12)
  28. * AllocTemporaryDirHandle               (F216/13)
  29. * DeallocateDirHandle                   (F216/14)
  30. * DeleteFakeRootDirectory               (E906)
  31. * GetDirectoryHandle                    (E900)
  32. * GetDriveConnectionId                  (EF02)
  33. * GetDirectoryPath                      (F216/01)
  34. * GetDriveFlag                          (EF01)     (6)
  35. * GetDriveHandle                        (EF00)     (6)
  36. * GetRelativeDriveDepth                 (E907)
  37. * GetSearchDriveVector                  (E901)
  38. * MapFakeRootDirectory                  (E905)
  39. * SetDirectoryHandle                    (F216/00)
  40. * SetDriveConnectionId                  (EF02)
  41. * SetDriveFlag                          (EF01)
  42. * SetDriveHandle                        (EF00)
  43. * SetSearchDriveVector                  (E902)
  44.  
  45.   Secondary Functions
  46.  
  47. * DeleteConnectionsDriveMappings
  48. * DeleteDriveMapping
  49. * GetEnvPath                            (BA..)
  50. * IsSearchDrive                         (BA..)
  51. * IsNetworkDrive                        (4409)
  52. * MapDrive
  53. * MapPermanentDrive
  54. * MapSearchDrive
  55. * SetEnvPath                            (BA..)
  56.  
  57. Entries (directory/file management)
  58. -----------------------------------
  59.  
  60. * ChangeDirectory                       (3B..)     (DOS)
  61. * ConvertPathToDirEntryId               (F217/F4)
  62. * CreateDirectory                       (F216/0A)
  63. * DeleteDirectory                       (F216/0B)
  64. * EraseFiles                            (F244)
  65. . FileServerFileCopy                    (F3..)
  66.   GetDirectoryInfo                      (F216/2D)  (3)
  67. * GetDirectoryEntry                     (F216/1F)  (3)
  68. . GetExtendedFileAttributes             (B600)     =F24E ???
  69. . GetFileAttributes                     (4300)     (DOS)
  70. * GetTrueEntryName                      (60..)     (DOS)
  71. * MapDirentryIdToPath                   (F217/F3)
  72.   MoveEntry                             (F216/2E)  (3) dir and files
  73. * PurgeSalvagableFile                   (F216/1D)  (3)
  74. * RecoverSalvagebleFile                 (F216/1C)  (3)
  75. * RenameDirectory                       (F216/0F)
  76. * ScanDirectoryInformation              (F216/02)
  77. * ScanDirectoryEntry                    (F216/1E)  (3)
  78. * ScanFileInformation                   (F217/0F)
  79.   ScanFilePhysical                      (F216/28)  (3)
  80. * ScanSalvagableFiles                   (F216/1B)  (3)
  81. * SetEntry                              (F216/25)  (3) dir and files
  82. . SetExtendedFileAttributes             (B601)     =F24F
  83. . SetFileAttributes                     (F246)     [4301]
  84. * SetFileInformation                    (F217/10)
  85.  
  86. * ScanDirRestrictions                   (F216/23)  (3)
  87. * SetDirRestriction                     (F216/24)  (3)
  88.  
  89.   Secondary functions:
  90.  
  91.   DeleteFile
  92.   GetFileHandle
  93.   IsFileShareable
  94.   FlagFileShareable
  95.   PurgeFiles          (by dirHandle,fileMask)
  96.   SalvageFiles        (by dirHandle,fileMask)
  97.   PurgeAllErasedFiles
  98.  
  99.  
  100. Trustees/Max. Rights Mask
  101. -------------------------
  102.  
  103. * DeleteTrustee                         (F216/2B)  (3)
  104. * GetEffectiveRights                    (F216/2A)  (3)
  105. . ModifyMaximumRightsMask               (F216/04)
  106. . ScanBinderyObjectTrusteePaths         (F217/47)
  107. * ScanEntryForTrustees                  (F216/26)  (3)
  108. * SetTrustee                            (F216/27)  (3)
  109.  
  110.  
  111. Not Implemented:
  112. ----------------
  113.  
  114. - AddTrusteeToDirectory                 (F216/0D)  (10)
  115. - AllocSpecialDirHandle                 (F216/16)  (2)
  116. - DeleteTrusteeFromDirectory            (F216/0E)  (10)
  117. - FileServerFileCopy                    (E6..)     (8)
  118. - GetEffectiveDirectoryRights           (F216/03)  (10)
  119. - GetPathFromDirEntryID                 (F216/1A)  (12)
  120. - GetVolumeInformation                  (F217/E9)  (1)
  121. - GetVolumeInfoWithHandle               (F216/15)  (5)
  122. - GetVolumeInfoWithNumber               (F212)     (4) [DA..]
  123. - PurgeErasedFiles                      (F216/10)  (8)
  124. - PurgeAllErasedFiles                   (F217/CE)  (8)
  125. - RestoreDirectoryHandle                (F216/18)  (2)
  126. - RestoreErasedFile                     (F216/11)  (8)
  127. - SaveDirectoryHandle                   (F216/17)  (2)
  128. - ScanDirectoryForTrustees              (F216/0C)  (9)
  129. - SetDirectoryInformation               (F216/19)  (11)
  130. - SetFileAttributes                     (E4..)     (7)
  131. - UpdateFileSize                        (E5..)     (7)
  132.  
  133.  
  134. Notes: (1) GetVolumeInformation. This call is NOT available in all 3.x versions.
  135.            (only with Nw 2.1 & 3.1x and CLIB.NLM dated before 11-11-92 )
  136.            This call is not implemented here. Replaced by GetVolumeUsage.
  137.        (2) not available in (all versions of) NW 3.x.
  138.        (3) NW 3.x (and upwards) only.
  139.        (4) Replaced by GetVolumeUsage and IsVolumeRemovable.
  140.        (5) Replaced by GetVolumeUsage and GetVolumeNameWithHandle.
  141.        (6) Information can also be obtained by calling GetDirectoryHandle.
  142.        (DOS) 'Normal' DOS call, extended by NetWare shell.
  143.        (7) Not supported by Adv.NW 3.x. Not implemented here.
  144.            These are functions using FCB's. If another function with the same
  145.            name is listed here, that function performs the same action.
  146.        (8) Not supported by Adv.NW 3.x. Not implemented here.
  147.            These functions have been replaced with calls marked (3)
  148.        (9) Replaced by a newer version: ScanEntryForTrustees.
  149.        (10) Replaced by DeleteTrustee, GetEffectiveRights and SetTrustee.
  150.        (11) Replaced by SetEntry
  151.        (12) Replaced by MapDirEntryIDtoPath
  152.  
  153.        }
  154.  
  155. Uses nwIntr,nwMisc,nwBindry,nwConn;
  156.  
  157. Var Result:Word;
  158.  
  159. Type TsearchDriveVector=array [1..17] of byte;
  160.  
  161.  
  162. CONST
  163.   DRIVE_UNUSED    = $00;
  164.   DRIVE_PERMANENT = $01; { Drive permanently assigned to fileserver directory }
  165.   DRIVE_TEMPORARY = $02; { Drive temporary assigned to FS dir. Released by EOJ }
  166.   DRIVE_NETWORK   = $03; { Normal drive mapping }
  167.   DRIVE_LOCAL     = $80; { Drive is local. ! By ORing with one of the above bits,
  168.                            it can be reassigned to a FS directory.}
  169.  
  170.   {Name Space Type constants}
  171.   NS_DOS     =0;
  172.   NS_MAC     =1;
  173.   NS_NFS     =2;
  174.   NS_FTAM    =3;
  175.   NS_HPFS    =4;
  176.  
  177.   { Attributes / Netware directory & file attributes }
  178.   A_NORMAL         =     $00; {file}
  179.   A_READ_ONLY      =     $01; {file}
  180.   A_HIDDEN         =     $02; {file/dir}
  181.   A_SYSTEM         =     $04; {file/dir}
  182.   A_EXECUTE_ONLY   =     $08; {file}
  183.   A_DIRECTORY      =     $10; {file}
  184.   A_NEEDS_ARCHIVED =     $20; {file}
  185.   A_undocumented   =     $40;
  186.   A_SHAREABLE      =     $80; {file}
  187.  
  188.   A_LO_SEARCH      =   $0100; {file}
  189.   A_MID_SEARCH     =   $0200; {file}
  190.   A_HI_SEARCH      =   $0400; {file}
  191.   A_RESERVED       =   $0800; {file/dir}
  192.   A_TRANSACTIONAL  =   $1000; {file}
  193.   A_INDEXED        =   $2000; {file}
  194.   A_READ_AUDIT     =   $4000; {file}
  195.   A_WRITE_AUDIT    =   $8000; {file}
  196.  
  197.   A_PURGE          = $010000; {file/dir}
  198.   A_RENAME_INHIBIT = $020000; {file/dir}
  199.   A_DELETE_INHIBIT = $040000; {file/dir}
  200.   A_COPY_INHIBIT   = $080000; {file}
  201.  
  202.   { Trustee Attributes / directory access rights }
  203.   TA_NONE       = $00;
  204.   TA_READ       = $01; {R open/read}
  205.   TA_WRITE      = $02; {W open/write}
  206.   TA_RESERVED   = $04; {  reserved, set to 0 }
  207.   TA_CREATE     = $08; {C create files or dirs}
  208.   TA_DELETE     = $10; {E delete files/dirs}
  209.   TA_ACCESS     = $20; {A set /delete trustees}
  210.   TA_SEARCH     = $40; {F directory can be searched/file is visible}
  211.   TA_MODIFY     = $80; {M modify dir/file attributes}
  212.   TA_SUPERVISOR =$100; {S supervisor rights to file or directory }
  213.  
  214.   { Entry Modify flags / see SetEntry }
  215.  
  216.   EM_ENTRYNAME      = $00000001;
  217.   EM_ATTRIBUTES     = $00000002;
  218.   EM_CREATIONTIME   = $0000000C; { date = $04, time = $08 }
  219.   EM_OWNERID        = $00000010;
  220.   EM_ARCHIVETIME    = $00000060; { date = $20, time = $40 }
  221.   EM_ARCHIVERID     = $00000080;
  222.   EM_MODIFYTIME     = $00000300; { date = $0100, time =$0200 }
  223.   EM_MODIFIERID     = $00000400;
  224.   EM_LASTACCESSTIME = $00000800; { date = $0800 }
  225.   EM_RIGHTSMASK     = $00001000;
  226.   EM_MAXDISKSPACE   = $00002000;
  227.  
  228. Type TvolUsage=record
  229.                totalBlocks,                    {static info}
  230.                freeBlocks,                     {dynamic}
  231.                purgableBlocks,                 {dynamic}
  232.                notYetPurgableBlocks,           {dynamic}
  233.                totalDirEntries,                {static}
  234.                availDirEntries,                {dynamic}
  235.                Flags               :LongInt;   {dynamic}
  236.                SectorsPerBlock     :byte;      {static/number of 512 byte sectors per block}
  237.                volumeName          :string[16];{static}
  238.                end;
  239.  
  240.      { used By ScanVolForRestrictions }
  241.      TobjVolRestr=array[1..64] of record
  242.                                   objId           :LongInt;
  243.                                   MaxAllowedBlocks:LongInt;
  244.                                   end;
  245.  
  246.  
  247. Type Tentry=record
  248.             EntryName       :String[16];
  249.  
  250.             NSType          :byte;       {namespace number}
  251.             DataForkSize    :Longint;    { =FileSize when NStype=0 (dos) }
  252.            {ResourceForkSize:Longint;    (Mac data) =0 when NStype=0 (dos)  }
  253.             FileSize        :Longint;    {FileSize=Resource+Data forksize }
  254.  
  255.             Attributes      :Longint;
  256.             RightsMask      :word;       {(4)}
  257.  
  258.             CreationTime,
  259.             ArchiveTime,
  260.             ModifyTime,
  261.             LastAccessTime,
  262.             DeleteTime      :TnovTime;   {salvagable file only}
  263.  
  264.             OwnerId,
  265.             ArchiverId,
  266.             ModifierId,
  267.             DeletorId       :Longint;    {salvagable file only}
  268.  
  269.             end;
  270.      { Note: (4) When used with ScanDirectoryInfo, this field
  271.                  contains the MaximumRightsMask.
  272.                  Otherwise, the InheritedRightsMask }
  273.  
  274. Type TdirRestrList=array[1..56] of record
  275.                                    Level:Byte;
  276.                                    MaxBlocks,
  277.                                    AvailableBlocks:Longint;
  278.                                    end;
  279.      {when MaxBlocks and Availableblocks are set to to $7FFFFFFF,
  280.       no restrictions are enforced -at this level-}
  281.  
  282. Type TtrusteeInformation=record
  283.                          NumberOfTrustees:Byte;
  284.                          TrusteeID    :array[1..20] of Longint;
  285.                          TrusteeRights:array[1..20] of Word;
  286.                          end;
  287.  
  288. {-------------------- Volumes----------------------- }
  289. {F216/05 [2.15c+]}
  290. Function GetVolumeNumber( volumeName:String; Var volumeNumber:Byte ):boolean;
  291. { Returns the volume number of a given volume name }
  292.  
  293. {F216/06 [2.15c+]}
  294. Function GetVolumeName( volumeNumber:Byte; Var volumeName:String ):boolean;
  295. { Returns the volume name of a give volume number [0..31].
  296.   If the volume is not mounted at the time of this call, a null-string is returned. }
  297.  
  298. {F216/2C [2.15c+]}
  299. Function GetVolumeUsage(volumeNumber:byte; Var VolUsage: TvolUsage):boolean;
  300.  
  301. {F212 [2.15c+]}
  302. Function IsVolumeRemovable( volumeNumber:Byte;
  303.                             Var volIsRemoveable:Boolean):boolean;
  304.  
  305. {F216/15 [2.15c+]}
  306. Function GetVolumeNameWithHandle( dirHandle:Byte;
  307.                                   Var volumeName:String ):boolean;
  308. {F216/29 [3.x]}
  309. Function GetObjectVolRestriction(VolumeNumber:byte; objId:LongInt;
  310.                   Var MaxAllowedBlocks,BlocksInUse:LongInt):boolean;
  311.  
  312. {F216/21 [3.x]}
  313. Function SetObjectVolRestriction(VolumeNumber:byte; objId,
  314.                                  MaxAllowedBlocks:LongInt):boolean;
  315. {F216/22 [3.x]}
  316. Function ClearObjectVolRestriction(VolumeNumber:byte; objId:LongInt):boolean;
  317.  
  318.  
  319. {F216/20 [3.x]}
  320. Function ScanVolForRestrictions(VolumeNumber:byte;
  321.                            {i/o} Var sequenceNbr:LongInt;
  322.                            {out} Var NbrOfObjects:byte;
  323.                                  Var ResultBuffer:TobjVolRestr):boolean;
  324. { 1st call: sequenceNbr=0,
  325.   after last call: sequenceNbr=0 again. }
  326.  
  327. {-------------------- Directory Handles/ Drives -------------}
  328.  
  329. {F216/01}
  330. Function GetDirectoryPath(DirHandle:byte; Var PathName:string):boolean;
  331.  
  332. {EF00 [2.0/2.1/3.x]}
  333. Function GetDriveHandle( DriveNumber:Byte; Var DirHandle:Byte ):boolean;
  334. { The call returns a pointer to the shell's Drive Handle Table. (32 bytes)
  335.   (Drives A..Z and temporary drives [\]^_' )
  336.   If a drive has been assigned a directory handle on the file server,
  337.   the handle can be found in the DHT at the position corresponding with the drive letter.}
  338.  
  339. {EF00 [2.0/2.1/3.x]}
  340. Function SetDriveHandle( DriveNumber:Byte; DirHandle:Byte ):boolean;
  341.  
  342. {E900 [2.0/2.1/3.x]}
  343. Function GetDirectoryHandle( DriveNumber:Byte; Var dirHandle,status:byte):Boolean;
  344. { Returns directory handle and status flags for a drive.                   }
  345. { Drivenumber = 0..31 (A..Z = 0..25) and temp drives (26..31)              }
  346.  
  347. {EF01 [2.0/2.1/3.x]}
  348. Function GetDriveFlag( DriveNumber:Byte; Var DriveStatus:Byte ):Boolean;
  349. { This call returns a pointer to the shell's Drive Flag Table (32 Bytes)
  350.   Each entry indicates a drive's status (permanent,temporary,local,unassigned)
  351.   For further explanation see the DRIVE_xxx constants.}
  352.  
  353. {EF01 [2.0/2.1/3.x]}
  354. Function SetDriveFlag( DriveNumber:Byte; DriveStatus:Byte ):Boolean;
  355.  
  356. {F216/14 [2.15c+]}
  357. function DeallocateDirHandle(DirHandle : Byte) : Boolean;
  358. { This function deletes a directory handle }
  359.  
  360.  
  361. {EF02 [2.0/2.1/3.x]}
  362. Function GetDriveConnectionID( DriveNumber:Byte; Var connID:Byte):boolean;
  363. { returns the servernumber (1..8) associated with a drive. }
  364.  
  365. {EF02 [2.0/2.1/3.x]}
  366. Function SetDriveConnectionID( DriveNumber:Byte; connID:Byte):boolean;
  367.  
  368. {F216/00 [2.15c+]}
  369. Function SetDirectoryHandle( sourceDirHandle:Byte; sourceDirPath:String;
  370.                              targetDirHandle:Byte ):boolean;
  371. { make handle 'targetHandle' point to the directory provided by
  372.   sourceHandle and/or sourceDirPath.                                      }
  373.  
  374. {F216/12 [2.15c+]}
  375. FUNCTION AllocPermanentDirHandle( DriveNumber:Byte;
  376.                                   DirHandle : byte; DirPath : string ;
  377.                                   var NewDirHandle, EffectiveRights: byte ) :boolean;
  378.  
  379. {F216/13 [2.15c+]}
  380. function AllocTemporaryDirHandle( DriveNumber:byte;
  381.                                   DirHandle : Byte; DirPath : String;
  382.                               var NewDirHandle,EffectiveRights : Byte) : Boolean;
  383. { Allocates a temporary directory handle, deleted automatically by EOJ. }
  384.  
  385. {E901}
  386. Function GetSearchDriveVector(Var vector:TsearchDriveVector):boolean;
  387.  
  388. {E902 }
  389. Function SetSearchDriveVector(vector:TsearchDriveVector):boolean;
  390.  
  391. {E905 (shell 3.01+)}
  392. Function MapFakeRootDirectory(DriveNumber:byte; DirPath:string):boolean;
  393.  
  394. {E906 (shell 3.01+)}
  395. Function DeleteFakeRootDirectory(DriveNumber:byte):boolean;
  396.  
  397. {E907 (shell 3.01+)}
  398. Function GetRelativeDriveDepth(DriveNumber:byte; Var depth:byte):boolean;
  399.  
  400. {BA.. }
  401. Function GetEnvPath(Var EnvPath:string):boolean;
  402.  
  403. {BA.. }
  404. Function SetEnvPath(EnvPath:string):boolean;
  405.  
  406.  
  407. {secondary }
  408. FUNCTION MapDrive(DriveNumber:byte; DirectoryPath:string;
  409.                   Root, Permanent:boolean):boolean;
  410.  
  411. {secondary }
  412. FUNCTION MapPermanentDrive(DriveNumber:byte; DirectoryPath:string;
  413.                            Root:boolean):boolean;
  414.  
  415. {secondary}
  416. Function MapSearchDrive(DriveNumber:byte; DirPath:string;
  417.                         PathPosition:byte;
  418.                         Insert,Root,Permanent:Boolean):boolean;
  419.  
  420. {secondary}
  421. Function DeleteDriveMapping(DriveNumber:Byte):boolean;
  422.  
  423. {secondary}
  424. Function DeleteConnectionsDriveMappings(ConnId:Byte):Boolean;
  425.  
  426. {secondary}
  427. Function IsSearchDrive(DriveNumber:byte):boolean;
  428.  
  429. {4409 }
  430. Function IsNetworkDrive(driveNumber:Byte):boolean;
  431. { isNetworkDrive is set to TRUE if the drive is a) a network drive, and
  432.   b) a legal drive letter was used.                                         }
  433.  
  434.  
  435. {------------------------- entries -----------------------------------------}
  436.  
  437. {F217/0F [2.15c+]}
  438. Function ScanFileInformation(DirHandle:Byte; FilePath:string;
  439.                              SearchAttrib:Byte;
  440.                         {i/o} VAR SequenceNbr:Integer;
  441.                         {out} VAR fileInfo:Tentry):Boolean;
  442.  
  443. {F217/F4 [3.0+]}
  444. Function ConvertPathToDirEntryId(dirHandle:Byte; dirPath:string;
  445.                              Var VolNbr    :byte;
  446.                              Var dirEntryID:LongInt):boolean;
  447. { aka ConvertPathToDirEntry / requires console rights }
  448.  
  449. {F216/02}
  450. Function ScanDirectoryInformation(dirHandle:byte; searchDirPath:string;
  451.                             {i/o} Var sequenceNumber:word;
  452.                            {out:} Var dirInfo:Tentry    ):boolean;
  453.  
  454. {F216/1F [2.15c+]}
  455. Function GetDirectoryEntry(DirHandle:byte;
  456.                            Var dirEntry:Tentry):boolean;
  457.  
  458. {F216/1E [2.15c+]}
  459. Function ScanDirectoryEntry(DirHandle:Byte; EntryName:string; SearchFlags:Longint;
  460.                       {i/o} Var EntryId:Longint;
  461.                       {out} Var Entry:Tentry    ):boolean;
  462.  
  463. {F217/F3 [3.0+]}
  464. Function MapDirEntryIdToPath(VolNbr:byte;DirEntryId:Longint; NStype:byte;
  465.                              Var ExtPath:string):boolean;
  466.  
  467. {F216/25 [2.15c+] }
  468. Function SetEntry(DirHandle:Byte;EntryId:Longint;SearchFlags:Byte;
  469.                   ModFlags:Longint; Entry:Tentry                ):boolean;
  470.  
  471. {F217/10 [2.15c+]}
  472. Function SetFileInformation(DirHandle:Byte; FilePath:string;
  473.                             SearchAttrib:Byte;
  474.                             fileInfo:TEntry):boolean;
  475.  
  476. {F216/1B [2.15c+]}
  477. Function ScanSalvagableFiles(DirHandle:Byte;
  478.                       {i/o}  Var EntryId:Longint;
  479.                       {out}  Var Entry:Tentry   ):boolean;
  480.  
  481. {F216/1D  [3.0+]}
  482. Function PurgeSalvagableFile(DirHandle:Byte;
  483.                              EntryId:Longint; FileName:string):boolean;
  484.  
  485. {F216/1C [3.0+] }
  486. Function RecoverSalvagableFile(dirHandle:Byte; EntryId:Longint;
  487.                                OldName,NewName:string):boolean;
  488.  
  489. {F244 [2.1x/3.x]}
  490. Function EraseFiles(dirHandle, searchAttrib:Byte; filePath:string ):boolean;
  491.  
  492. {60.. (extended DOS call)}
  493. Function GetTrueEntryName(DirPath:string; Var CanonicalPath:string):boolean;
  494.  
  495.  
  496. {F216/0F [2.0/2.1/3.x]}
  497. Function RenameDirectory( dirHandle:Byte; dirPath, newDirName :String):Boolean;
  498.  
  499. {F216/0B [2.15c+]}
  500. Function DeleteDirectory(DirHandle:Byte; DirPath:string):boolean;
  501.  
  502. {F216/0A [2.15+]}
  503. Function CreateDirectory(DirHandle:Byte; DirPath:string; MaxRightsMask:byte):boolean;
  504.  
  505. {3B.. }
  506. Function ChangeDirectory(DirPath:string):boolean;
  507.  
  508.  
  509. {F216/24 [3.0+]}
  510. Function SetDirRestriction(DirHandle:Byte; DiskSpaceLimit:Longint):boolean;
  511.  
  512. {F216/23 [3.0+]}
  513. Function ScanDirRestrictions(DirHandle:Byte;
  514.                            Var NumberOfEntries:Byte;
  515.                            Var RestrInfo:TdirRestrList):boolean;
  516.  
  517. {--------------------------- Rights/trustees ---------------------------}
  518.  
  519. {F216/27 [3.0+]}
  520. Function SetTrustee(DirHandle:Byte;DirPath:string;
  521.                     TrusteeObjectID:Longint;
  522.                     RightsMask:Word               ):boolean;
  523.  
  524. {F216/2B [3.0+]}
  525. Function DeleteTrustee(DirHandle:Byte;DirPath:String;
  526.                        TrusteeObjectId:Longint):boolean;
  527.  
  528. {F216/2A [3.0+]}
  529. function GetEffectiveRights(DirHandle:Byte;DirPath:String;
  530.                         var Rights:Word) : Boolean;
  531.  
  532. {F216/04 [2.15c+]}
  533. Function ModifyMaximumRightsMask(DirHandle:Byte;DirPath:string;
  534.                                  RevokeRightsMask,GrantRightsMask:Word):boolean;
  535.  
  536.  
  537. {F217/47 [2.15c+]}
  538. Function ScanBinderyObjectTrusteePaths(TrusteeObjectId:Longint;
  539.                                        VolumeNumber:Byte;
  540.                              {i/o} Var SequenceNumber:word;
  541.                              {out} Var AccessMask:Word;
  542.                                    Var Path:string        ):boolean;
  543.  
  544. {F216/26 [3.0+]}
  545. Function ScanEntryForTrustees(DirHandle:Byte;DirPath:String;
  546.                     {i/o} Var SequenceNumber:Byte;
  547.                     {out} Var TrusteeInfo: TtrusteeInformation):boolean;
  548.  
  549. IMPLEMENTATION{============================================================}
  550.  
  551. {$IFDEF MSDOS}
  552. uses dos; { file handles / 'normal' file attributes }
  553. {$ENDIF}
  554.  
  555. Type TintEntry=record  { Unit internal Entry type }
  556.          {  0} _res1          :Longint; { low word = Dir Id of parent Dir }
  557.          {  4} _attrib        :Longint;
  558.          {  8} _res2          :word;
  559.          { 10} _NStype        :Byte;
  560.          { 11} _name          :string[12];
  561.          { 24} _creationTime  :Longint;
  562.          { 28} _OwnerId       :Longint;    { hi-lo}
  563.          { 32} _ArchiveTime   :Longint;
  564.          { 36} _ArchiverId    :Longint;    { hi-lo}
  565.          { 40} _modifyTime    :Longint;
  566.  
  567.          { 44} _ModifierId    :Longint;               { files only }
  568.          { 48} _ForkSize      :Longint;               { files only }
  569.          { 52} _res3          :array[1..44] of byte;  { Trustee obj IDs and Tr. rights }
  570.          { 96} _FileRightsMask:word;                  { files only }
  571.          { 98} _AccessDate    :word;                  { files only }
  572.  
  573.          {100} _DirRightsMask :word;                  { directories only }
  574.          {102} _res4          :word; {Unique Dir ID, hi-lo} { directories only }
  575.          {104} _DeleteTime    :Longint;               { salvageable files only }
  576.          {108} _DeletorID     :LongInt;               { salvageable files only }
  577.          {112} _res5          :array[1..16] of byte;
  578.          {128} end;
  579.  
  580. Procedure Convert2ExtEntry(Var Ie:TintEntry;Var Oe:Tentry);
  581. begin
  582. FillChar(Oe,Sizeof(Tentry),#$0);
  583. with Ie,Oe
  584.  do begin
  585.     Attributes:=_Attrib;
  586.     NStype:=_NStype;
  587.     Entryname:=_name;
  588.     DosTime2NovTime(_CreationTime,CreationTime);
  589.     OwnerId:=Lswap(_OwnerId); {force lo-hi}
  590.     DosTime2NovTime(_ArchiveTime,ArchiveTime);
  591.     ArchiverId:=Lswap(_ArchiverID); {force lo-hi}
  592.     DosTime2NovTime(_ModifyTime,ModifyTime);
  593.     if (_attrib and $10)>0 { is entry a directory ? }
  594.      then begin
  595.           RightsMask:=_DirRightsMask;
  596.           end
  597.      else begin
  598.           ModifierId:=LSwap(_ModifierId); {force lo-hi}
  599.           DataForksize:=_Forksize;
  600.           if _NSType=0
  601.            then FileSize:=_ForkSize;
  602.           RightsMask:=_FileRightsMask;
  603.           DosTime2NovTime(MakeLong(_accessDate,0),LastAccessTime);
  604.           DosTime2NovTime(_DeleteTime,DeleteTime);
  605.           DeletorId:=Lswap(_DeletorID); {force lo-hi}
  606.           end;
  607.     end;
  608. end;
  609.  
  610. Procedure Convert2IntEntry(Var Oe:TEntry;Var Ie:TIntEntry);
  611. Var TempTime:Longint;
  612. begin
  613. FillChar(Ie,Sizeof(Tentry),#$0);
  614. with Ie,Oe
  615.  do begin
  616.     _Attrib:=Attributes;
  617.     _NStype:=NStype;
  618.     _Name:=EntryName;
  619.     NovTime2DosTime(CreationTime,_CreationTime);
  620.     _OwnerId:=Lswap(OwnerId); {force hi-lo}
  621.     NovTime2DosTime(ArchiveTime,_ArchiveTime);
  622.     _ArchiverId:=Lswap(ArchiverId); {force hi-lo}
  623.     NovTime2DosTime(ModifyTime,_ModifyTime);
  624.     if (Attributes and $10)>0 { is entry a directory ? }
  625.      then begin
  626.           _DirRightsMask:=RightsMask;
  627.           end
  628.      else begin
  629.           _ModifierId:=Lswap(ModifierId); { force hi-lo }
  630.           _ForkSize:=DataForkSize;
  631.           _FileRightsMask:=RightsMask;
  632.           NovTime2DosTime(LastAccessTime,TempTime);
  633.           _AccessDate:=HiLong(TempTime);
  634.           NovTime2DosTime(DeleteTime,_DeleteTime);
  635.           _DeletorID:=Lswap(DeletorId); { force hi-lo }
  636.           end;
  637.     end;
  638. end;
  639.  
  640. Procedure ConvertPathToVolFormat(Var path:string);
  641. { reformat \\server\vol\path to VOL:PATH
  642.            server/vol:path   to VOL:PATH  }
  643. Var pcolon,pslash:byte;
  644. begin
  645. if (Path[0]>#1) and (Path[1]='\') and (Path[2]='\')
  646.  then begin
  647.       delete(Path,1,2);
  648.       Path:=Path+'\';
  649.       pslash:=pos('\',Path);
  650.       if pslash>0
  651.        then begin
  652.             delete(Path,1,pslash); { remove servername from path }
  653.             pslash:=pos('\',Path);
  654.             if pslash>0
  655.              then Path:=copy(Path,1,pslash-1)+':'+copy(Path,pslash+1,255);
  656.             end;
  657.        while Path[ord(Path[0])]='\' do dec(Path[0]);
  658.        end
  659.  else begin
  660.       pcolon:=pos(':',path);
  661.       if (path[0]>#3) and (pcolon>3)
  662.        then begin
  663.             pslash:=pos('/',path);
  664.             if (pslash=0) or (pslash>pcolon)
  665.              then pslash:=pos('\',path);
  666.             if (pslash>0) and (pslash<pcolon)
  667.              then delete(path,1,pslash); { remove 'server/' }
  668.             end;
  669.       end;
  670. end;
  671.  
  672.  
  673. {------------------ Volume Management --------------------------------------}
  674.  
  675.  
  676. {F216/2C [2.15c+]}
  677. Function GetVolumeUsage(VolumeNumber:byte; Var VolUsage: TvolUsage):boolean;
  678. Type Treq=record
  679.           len:word;
  680.           subf:byte;
  681.           volNbr:byte;
  682.           end;
  683.      Trep=TvolUsage;
  684.      TPreq=^Treq;
  685.      TPrep=^Trep;
  686. begin
  687. with TPreq(GlobalReqBuf)^
  688.  do begin
  689.     len:=SizeOf(Treq)-2;
  690.     subf:=$2C;
  691.     volNbr:=VolumeNumber;
  692.     end;
  693. F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
  694. VolUsage:=TPrep(GlobalReplyBuf)^;
  695. IF (Volusage.totalBlocks=0)
  696.    or (volusage.volumename='')
  697.  then result:=$98;
  698. GetVolumeUsage:=(result=0);
  699. {resultcodes:
  700.   00 success; 98h Volume doesn't exist / not mounted }
  701. end;
  702.  
  703.  
  704. {F216/06 [2.15c+]}
  705. Function GetVolumeName(volumeNumber:Byte; Var volumeName:String ):boolean;
  706. { Returns the volume name of a give volume number [0..31].
  707.   If the volume name doesn't exist, or the volume is not mounted
  708.   at the time of this call, an error $98 results and volName is set to '' }
  709. Type Treq=record
  710.           len     :word;
  711.           subFunc :byte;
  712.           volNbr :Byte;
  713.           end;
  714.      Trep=record
  715.           _volName:String[16];
  716.           end;
  717.      TPreq=^Treq;
  718.      TPrep=^Trep;
  719. Begin
  720. WITH TPreq(GlobalReqBuf)^
  721.  do begin
  722.     len:=SizeOf(Treq)-2;
  723.     subFunc:=$06;
  724.     volNbr:=volumeNumber
  725.     end;
  726. F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
  727. volumeName:=TPrep(GlobalReplyBuf)^._volName;
  728. if volumeName=''
  729.  then result:=$98;
  730. GetVolumeName:=(result=0)
  731. {resultcodes:
  732.   00 success; 98h Volume doesn't exist / not mounted }
  733. end;
  734.  
  735.  
  736.  
  737. {F216/05 [2.15c+]}
  738. Function GetVolumeNumber( volumeName:String; Var volumeNumber:Byte ):boolean;
  739. { Returns the volume number [0..31] of a given volume name.
  740.   The volumename can have a maximum of 16 characters. Wildcards are
  741.   allowed, the volume number of the first match will be returned.
  742.   The name of the volume may be supplied with ('SYS:') or without
  743.   the colon ('SYS'). }
  744. Type Treq=record
  745.           len      :word;
  746.           subFunc  :byte;
  747.           volName  :String[16];
  748.           end;
  749.      Trep=record
  750.           volNbr  :Byte;
  751.           end;
  752.      TPreq=^Treq;
  753.      TPrep=^Trep;
  754. Begin
  755. WITH TPreq(GlobalReqBuf)^
  756.  do begin
  757.     subFunc:=$05;
  758.     if volumeName[0]>#16
  759.      then volumeName[0]:=#16;
  760.     volName:=volumeName;
  761.     if volname[ord(volName[0])]=':'
  762.      then dec(volName[0]);
  763.     len:=2+ord(volName[0]);
  764.     F2SystemCall($16,len+2,SizeOf(Trep),result);
  765.     end;
  766. volumenumber:=TPrep(GlobalReplyBuf)^.volNbr;
  767. getVolumeNumber:=(result=0)
  768. {resultcodes:
  769.   00 success; 98h volume doesn't exist }
  770. end;
  771.  
  772.  
  773. {F216/15 [2.15c+]}
  774. Function GetVolumeNameWithHandle( dirHandle:Byte;
  775.                                   Var volumeName:String ):boolean;
  776. Type Treq=record
  777.           len        :word;
  778.           subFunc    :byte;
  779.           _dirHandle :Byte;
  780.           end;
  781.      Trep=record
  782.           _sectPerBlock :Word; {hi-lo}
  783.           _TotalBlocks  :Word; {hi-lo}
  784.           _availBlocks  :Word; {hi-lo} { Use GetVolumeUsage for the other fields }
  785.           _TotalDirSlots:Word; {hi-lo}
  786.           _availDirSlots:Word; {hi-lo}
  787.           _volName      :array[1..16] of byte;
  788.           _volRemoveable:Word; {hi-lo}
  789.           end;
  790.      TPreq=^Treq;
  791.      TPrep=^Trep;
  792. Begin
  793. WITH TPreq(GlobalReqBuf)^
  794.  do begin
  795.     len:=SizeOf(Treq)-2;
  796.     subFunc:=$15;
  797.     _dirHandle:=dirHandle;
  798.     end;
  799. F2SystemCall($16,Sizeof(Treq),SizeOf(Trep),result);
  800. ZStrCopy(volumeName,TPrep(GlobalReplyBuf)^._volName,16);
  801. if volumeName=''
  802.  then result:=$9B; { Invalid directory handle }
  803. getVolumeNameWithHandle:=(result=0)
  804. { resultcodes: 00 success; $9B invalid directory handle }
  805. end;
  806.  
  807.  
  808. {F212 [2.15c+]}
  809. Function IsVolumeRemovable( volumeNumber:Byte;
  810.                             Var volIsRemoveable:Boolean):boolean;
  811. { stripped down version of the GetVolumeInfoWithNumber call }
  812. Type Treq=Byte;
  813.      Trep=record
  814.           _sectPerBlock  :Word; {hi-lo}
  815.           _TotalBlocks   :Word; {hi-lo}
  816.           _availBlocks   :Word; {hi-lo}
  817.           _TotalDirSlots :Word; {hi-lo}
  818.           _availDirSlots :Word; {hi-lo}
  819.           _volName       :array[1..16] of byte;
  820.           _volRemoveable :Word; {hi-lo}
  821.           end;
  822.      TPreq=^Treq;
  823.      TPrep=^Trep;
  824. Begin
  825. TPreq(GlobalReqBuf)^:=volumeNumber;
  826. F2SystemCall($12,SizeOf(Treq),SizeOf(Trep),result);
  827. With TPrep(GlobalReplyBuf)^
  828.  do begin
  829.     volIsRemoveable:=(_volRemoveable>0);
  830.     if _volName[1]=0
  831.      then result:=$98;
  832.     end;
  833. IsVolumeRemovable:=(result=0);
  834. { resultcodes: 00 success; 98h Invalid volume number / volume not mounted }
  835. end;
  836.  
  837. {F216/22 [3.x]}
  838. Function ClearObjectVolRestriction(VolumeNumber:byte; objId:LongInt):boolean;
  839. { If the objId doesn't exist, no error is returned. }
  840. Type Treq=record
  841.           len:word;
  842.           subFunc:byte;
  843.           _volNbr:byte;
  844.           _objId:LongInt; { hi-lo }
  845.           end;
  846.      TPreq=^Treq;
  847. Begin
  848. WITH TPreq(GlobalReqBuf)^
  849.  do begin
  850.     len:=SizeOf(Treq)-2;
  851.     subFunc:=$22;
  852.     _volNbr:=VolumeNumber;
  853.     _objId:=Lswap(objId); { force hi-lo }
  854.     end;
  855. F2SystemCall($16,SizeOf(Treq),0,result);
  856. ClearObjectVolRestriction:=(result=0)
  857. { $8C No supervisor rights }
  858. end;
  859.  
  860. {F216/29 [3.x]}
  861. Function GetObjectVolRestriction(VolumeNumber:byte; objId:LongInt;
  862.                   Var MaxAllowedBlocks,BlocksInUse:LongInt):boolean;
  863. { If MaxAllowedBlocks is equal to $40000000 on return, there are no
  864.   disk restrictions for the object on this volume. }
  865. { You need not be logged in to use this call. }
  866. Type Treq=record
  867.           len    :word;
  868.           subFunc:byte;
  869.           _volNbr:byte;
  870.           _objId :Longint; {hi-lo}
  871.           end;
  872.      Trep=record
  873.           _MaxAllowedBlocks,
  874.           _BlocksInUse      :Longint;
  875.           end;
  876.      TPreq=^Treq;
  877.      TPrep=^Trep;
  878. Var objName:string;
  879.     objType:word;
  880. Begin
  881. WITH TPreq(GlobalReqBuf)^
  882.  do begin
  883.     len    :=SizeOf(Treq)-2;
  884.     subFunc:=$29;
  885.     _volNbr:=VolumeNumber;
  886.     _objId :=Lswap(objId); {force hi-lo}
  887.     end;
  888. F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
  889. With TPrep(GlobalReplyBuf)^
  890.  do begin
  891.     MaxAllowedBlocks:=_MaxAllowedBlocks;
  892.     BlocksInUse:=_BlocksInUse;
  893.     If BlocksInUse=0
  894.      then if NOT nwBindry.GetBinderyObjectName(objId,objName,objType)
  895.            then result:=$FF;
  896.     end;
  897. GetObjectVolRestriction:=(result=0)
  898. {resultcodes: 00 success; $FF Invalid objectId }
  899. end;
  900.  
  901. {F216/20 [3.x]}
  902. Function ScanVolForRestrictions(VolumeNumber:byte;
  903.                            {i/o} Var sequenceNbr:LongInt;
  904.                            {out} Var NbrOfObjects:byte;
  905.                                  Var ResultBuffer:TobjVolRestr):boolean;
  906. { 1st call: sequenceNbr=0,
  907.   // n-th call: sequenceNbr(n):=sequenceNbr(n-1)+NbrOfObjects
  908.   // (addition done by function itself)
  909.  
  910.   after last call: sequenceNbr=0 again. }
  911. Type Treq=record
  912.           len:word;
  913.           subFunc:byte;
  914.           _volNbr:byte;
  915.           _seqNbr:LongInt; { lo-hi !}
  916.           end;
  917.      Trep=record
  918.           _NbrOfObjects:byte;
  919.           _buff        :TobjVolRestr;
  920.           end;
  921.      TPreq=^Treq;
  922.      TPrep=^Trep;
  923. Var t:byte;
  924. Begin
  925. WITH TPreq(GlobalReqBuf)^
  926.  do begin
  927.     len:=SizeOf(Treq)-2;
  928.     subFunc:=$20;
  929.     _volNbr:=VolumeNumber;
  930.     _seqNbr:=sequenceNbr;
  931.     end;
  932. F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
  933. if result=0
  934.  then begin
  935.       With TPrep(GlobalReplyBuf)^
  936.        do begin
  937.           NbrOfObjects:=_NbrOfObjects;
  938.           ResultBuffer:=_buff;
  939.           For t:=1 to NbrOfObjects
  940.            do ResultBuffer[t].objId:=Lswap(_buff[t].ObjId);
  941.           if _NbrOfObjects=0
  942.            then result:=$FF
  943.            else sequenceNbr:=sequenceNbr+_NbrOfObjects;
  944.           end
  945.       end
  946.  else NbrOfObjects:=0;
  947. ScanVolForRestrictions:=(result=0)
  948. { $98 VolumeNumber doesn't exist;
  949.   $FF No New restriction data (end of iteration) }
  950. end;
  951.  
  952. {F216/21 [3.x]}
  953. Function SetObjectVolRestriction(VolumeNumber:byte; objId,MaxAllowedBlocks:LongInt):boolean;
  954. { If the objId doesn't exist, no error is returned. }
  955. Type Treq=record
  956.           len    :word;
  957.           subFunc:byte;
  958.           _volNbr:byte;
  959.           _objId :Longint;    {hi-lo}
  960.           _maxBlocks:LongInt; {lo-hi !!}
  961.           end;
  962.      TPreq=^Treq;
  963. Begin
  964. WITH TPreq(GlobalreqBuf)^
  965.  do begin
  966.     len:=SizeOf(Treq)-2;
  967.     subFunc:=$21;
  968.     _volNbr:=VolumeNumber;
  969.     _objId:=Lswap(objId); { force hi-lo }
  970.     _maxBlocks:=MaxAllowedBlocks;
  971.     end;
  972. F2SystemCall($16,SizeOf(Treq),0,result);
  973. SetObjectVolRestriction:=(result=0)
  974. { $8C No supervisor Rights }
  975. end;
  976.  
  977.  
  978. {--------------Dir handles/ drive mappings----------------------------------}
  979.  
  980.  
  981. {BA.. }
  982. Function GetEnvPath(Var EnvPath:string):boolean; {#d}
  983. Type Tarr=array[1..2048] of byte;
  984. Var regs:TTregisters;
  985.     penv:^Tarr;
  986.     i,envSize:word;
  987.     state:byte;
  988. begin
  989. regs.ah:=$BA;
  990. RealModeIntr($21,regs);
  991. envSize:=byte(nwPtr(regs.dx-1,3)^) SHL 4;
  992. penv:=nwPtr(regs.dx,0);
  993. i:=1;
  994. state:=0;
  995. while (i<envSize) and (state<5)
  996.  do begin
  997.     CASE state of
  998.      4:if penv^[i]=ord('=')
  999.         then state:=5
  1000.         else state:=0;
  1001.      3:if penv^[i]=ord('H')
  1002.         then state:=4
  1003.         else state:=0;
  1004.      2:if penv^[i]=ord('T')
  1005.         then state:=3
  1006.         else state:=0;
  1007.      1:if penv^[i]=ord('A')
  1008.         then state:=2
  1009.         else state:=0;
  1010.      0:if penv^[i]=ord('P')
  1011.         then state:=1;
  1012.      end; {case}
  1013.      inc(i);
  1014.      end;
  1015.  
  1016. if state<5
  1017.  then begin
  1018.       result:=$300;
  1019.       GetEnvPath:=false;
  1020.       exit;
  1021.       end;
  1022. EnvPath:='';
  1023. while (i<=envSize) and (penv^[i]<>0)
  1024.  do begin
  1025.     EnvPath:=EnvPath+chr(penv^[i]);
  1026.     inc(i);
  1027.     end;
  1028. if i>envSize
  1029.  then begin
  1030.       result:=$301;
  1031.       GetEnvPath:=false;
  1032.       exit;
  1033.       end;
  1034. result:=0;
  1035. GetEnvPath:=true;
  1036. { 00  successful
  1037.   300 'Path' not found
  1038.   301 Path value could not be read }
  1039. end;
  1040.  
  1041. {BA.. }
  1042. Function SetEnvPath(EnvPath:string):boolean; {#d}
  1043. Type Tarr=array[1..2048] of byte;
  1044. Var regs:TTregisters;
  1045.     penv:^Tarr;
  1046.     i,t,envSize:word;
  1047.     state:byte;
  1048.     pbegin,pend:word;
  1049.     NewPathSize,OldPathSize:byte;
  1050.     diff:integer;
  1051.     sVector:TsearchDriveVector;
  1052.     Vecind,p:byte;
  1053.     dn:Byte;
  1054. begin
  1055. Upstring(EnvPath);
  1056. If pos('PATH=',envPath)=1
  1057.  then delete(EnvPath,1,5);
  1058. regs.ah:=$BA;
  1059. RealModeIntr($21,regs);
  1060. envSize:=word(nwPtr(regs.dx-1,3)^) SHL 4;
  1061. penv:=nwPtr(regs.dx,0);
  1062.  
  1063. i:=1;
  1064. state:=0;
  1065. while (i<envSize) and (state<5)
  1066.  do begin
  1067.     CASE state of
  1068.      0:if penv^[i]=ord('P')
  1069.         then state:=1;
  1070.      1:if penv^[i]=ord('A')
  1071.         then state:=2
  1072.         else state:=0;
  1073.      2:if penv^[i]=ord('T')
  1074.         then state:=3
  1075.         else state:=0;
  1076.      3:if penv^[i]=ord('H')
  1077.         then state:=4
  1078.         else state:=0;
  1079.      4:if penv^[i]=ord('=')
  1080.         then state:=5
  1081.         else state:=0;
  1082.      end; {case}
  1083.      inc(i);
  1084.      end;
  1085.  
  1086. if state<5
  1087.  then begin
  1088.       result:=$300;
  1089.       SetEnvPath:=false;
  1090.       exit;
  1091.       end;
  1092. { determine starting and ending character of path variable }
  1093. pbegin:=i;
  1094. while (i<envSize) and (penv^[i]<>0)
  1095.  do inc(i);
  1096. if i>envSize
  1097.  then begin
  1098.       result:=$301;
  1099.       SetEnvPath:=false;
  1100.       exit;
  1101.       end;
  1102. dec(i);
  1103. pend:=i;
  1104.  
  1105. { determine end of 'active' environment / marked by $00 00}
  1106. while (i<envSize) and NOT ((penv^[i]=0) and (penv^[i+1]=0))
  1107.  do inc(i);
  1108. if i=envSize
  1109.  then begin
  1110.       result:=$301;
  1111.       SetEnvPath:=false;
  1112.       exit;
  1113.       end;
  1114. inc(i); { penv^[i] = 'second' 00, end-of-environment }
  1115.  
  1116. OldPathSize:=1+pend-pbegin;
  1117. NewPathSize:=ord(EnvPath[0]);
  1118.  
  1119. If (i+NewPathSize-OldPathSize)>envSize
  1120.  then begin
  1121.       result:=$302;
  1122.       SetEnvPath:=false;
  1123.       exit;
  1124.       end;
  1125.  
  1126. diff:=NewPathSize-OldPathSize;
  1127. if diff>0
  1128.  then for t:=i downto pend
  1129.       do penv^[t+diff]:=penv^[t];
  1130. if diff<0
  1131.  then for t:=pend to i
  1132.       do penv^[t+diff]:=penv^[t];
  1133. Move(EnvPath[1],penv^[pbegin],NewPathSize);
  1134.  
  1135. FillChar(Svector,SizeOf(TsearchDriveVector),#$FF);
  1136. VecInd:=1;
  1137. REPEAT
  1138. p:=pos(':',envPath);
  1139. if p>0
  1140.  then begin
  1141.       dn:=ord(ord(envPath[p-1])-ord('A'));
  1142.       p:=pos(';',envPath);
  1143.       if p=0
  1144.        then envPath:=''
  1145.        else delete(envPath,1,p);
  1146.       IF IsNetworkDrive(dn)
  1147.        then begin
  1148.             Svector[VecInd]:=dn;
  1149.             inc(VecInd)
  1150.             end;
  1151.       end;
  1152. UNTIL (p=0) or (VecInd=17);
  1153. SetSearchDriveVector(Svector);
  1154.  
  1155. result:=0;
  1156. SetEnvPath:=true;
  1157. { 00  successful
  1158.   300 'Path' not found
  1159.   301 Environment failure
  1160.   302 Environment overflow (new path too large) }
  1161. end;
  1162.  
  1163.  
  1164. {F216/01}
  1165. Function GetDirectoryPath(DirHandle:byte; Var PathName:string):boolean;
  1166. { path includes volumename }
  1167. Type Treq=record
  1168.           len    :word;
  1169.           subFunc:byte;
  1170.           _dh    :byte;
  1171.           end;
  1172.      Trep=record
  1173.           DirPath:string[255];
  1174.           end;
  1175.      TPreq=^Treq;
  1176.      TPrep=^Trep;
  1177. Begin
  1178. WITH TPreq(GlobalReqBuf)^
  1179.  do begin
  1180.     len:=SizeOf(Treq)-2;
  1181.     subFunc:=$01;
  1182.     _dh:=DirHandle;
  1183.     end;
  1184. F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
  1185. PathName:=TPrep(GlobalReplyBuf)^.DirPath;
  1186. GetDirectoryPath:=(result=0)
  1187. { 00 Successful      9B Bad directory handle }
  1188. end;
  1189.  
  1190. {EF02 [2.0/2.1/3.x]}
  1191. Function GetDriveConnectionID( DriveNumber:Byte; Var connID:Byte):boolean;
  1192. { returns the servernumber (1..8) associated with a drive. }
  1193. Type pArr=^arr;
  1194.      arr=array[0..31] of byte;
  1195. Var regs:TTregisters;
  1196. begin
  1197. regs.ax:=$EF02;
  1198. RealModeIntr($21,Regs);
  1199. If DriveNumber>31
  1200.  then result:=$0105
  1201.  else begin
  1202.       connID:=Parr(nwPtr(Regs.es,regs.si))^[DriveNumber];
  1203.       Result:=0;
  1204.       end;
  1205. GetDriveConnectionID:=(Result=0);
  1206. end;
  1207.  
  1208. {EF02 [2.0/2.1/3.x]}
  1209. Function SetDriveConnectionID( DriveNumber:Byte; connID:Byte):boolean;
  1210. Type pArr=^arr;
  1211.      arr=array[0..31] of byte;
  1212. Var regs:TTregisters;
  1213. begin
  1214. regs.ax:=$EF02;
  1215. RealModeIntr($21,Regs);
  1216. If DriveNumber>31
  1217.  then result:=$0105
  1218.  else begin
  1219.       Parr(nwPtr(Regs.es,regs.si))^[DriveNumber]:=connId;
  1220.       Result:=0;
  1221.       end;
  1222. SetDriveConnectionID:=(Result=0);
  1223. end;
  1224.  
  1225.  
  1226. {EF00 [2.0/2.1/3.x]}
  1227. Function GetDriveHandle( DriveNumber:Byte; Var DirHandle:Byte ):boolean;
  1228. { The call returns a pointer to the shell's Drive Handle Table. (32 bytes)
  1229.   (Drives A..Z and temporary drives [\]^_' )
  1230.   If a drive has been assigned a directory handle on the file server,
  1231.   the handle can be found in the DHT at the position corresponding with the drive letter.}
  1232. Type pArr=^arr;
  1233.      arr=array[0..31] of byte;
  1234. Var regs:TTregisters;
  1235. begin
  1236. regs.ax:=$EF00;
  1237. RealModeIntr($21,regs);
  1238. if DriveNumber>31
  1239.  then result:=$0105
  1240.  else begin
  1241.       DirHandle:=Parr(nwPtr(Regs.Es,Regs.Si))^[DriveNumber];
  1242.       Result:=0;
  1243.       end;
  1244. GetDriveHandle:=(Result=0);
  1245. end;
  1246.  
  1247. {EF00 [2.0/2.1/3.x]}
  1248. Function SetDriveHandle( DriveNumber:Byte; DirHandle:Byte ):boolean;
  1249. Type pArr=^arr;
  1250.      arr=array[0..31] of byte;
  1251. Var regs:TTregisters;
  1252. begin
  1253. regs.ax:=$EF00;
  1254. RealModeIntr($21,regs);
  1255. if DriveNumber>31
  1256.  then result:=$0105
  1257.  else begin
  1258.       Parr(nwPtr(Regs.Es,Regs.Si))^[DriveNumber]:=DirHandle;
  1259.       Result:=0;
  1260.       end;
  1261. SetDriveHandle:=(Result=0);
  1262. end;
  1263.  
  1264. {EF01 [2.0/2.1/3.x]}
  1265. Function GetDriveFlag( DriveNumber:Byte; Var DriveStatus:Byte ):Boolean;
  1266. { This call returns a pointer to the shell's Drive Flag Table (32 Bytes)
  1267.   Each entry indicates a drive's status (permanent,temporary,local,unassigned)
  1268.   For further explanation see the DRIVE_xxx constants.}
  1269. Type pArr=^arr;
  1270.      arr=array[0..31] of byte;
  1271. Var regs:TTregisters;
  1272. begin
  1273. regs.ax:=$EF01;
  1274. RealModeIntr($21,Regs);
  1275. If DriveNumber>31
  1276.   then result:=$0105
  1277.   else begin
  1278.        DriveStatus:=Parr(nwPtr(Regs.es,regs.si))^[DriveNumber];
  1279.        Result:=0;
  1280.        end;
  1281. GetDriveFlag:=(Result=0);
  1282. end;
  1283.  
  1284. {EF01 [2.0/2.1/3.x]}
  1285. Function SetDriveFlag( DriveNumber:Byte; DriveStatus:Byte ):Boolean;
  1286. Type pArr=^arr;
  1287.      arr=array[0..31] of byte;
  1288. Var regs:TTregisters;
  1289. begin
  1290. regs.ax:=$EF01;
  1291. RealModeIntr($21,Regs);
  1292. If DriveNumber>31
  1293.   then result:=$0105
  1294.   else begin
  1295.        Parr(nwPtr(Regs.es,regs.si))^[DriveNumber]:=DriveStatus;
  1296.        Result:=0;
  1297.        end;
  1298. SetDriveFlag:=(Result=0);
  1299. end;
  1300.  
  1301.  
  1302. {E900 [2.0/2.1/3.x]}
  1303. Function GetDirectoryHandle( DriveNumber:Byte; Var dirHandle,status:byte):Boolean;
  1304. { Returns directory handle and status flags for a drive.                   }
  1305. { Drivenumber = 0..31 (A..Z = 0..25) and temp drives (26..31)              }
  1306. { Status Byte
  1307.   7  6  5  4  3  2  1  0
  1308.   |                 |  +-Permenant Directory Handle
  1309.   |                 +----Temporary Directory Handle
  1310.   +----------------------Mapped to a local drive    }
  1311. { in case of an invalid driveNumber, handle and status will be set to 0 }
  1312. Var Regs:TTRegisters;
  1313. begin
  1314. With Regs
  1315. do begin
  1316.    AX:=$E900;
  1317.    DX:=DriveNumber;
  1318.    RealModeIntr($21,Regs);
  1319.    { AH = Status Flags;
  1320.           01 mapped to a permanent dir handle;
  1321.           02 mapped to a temporary dir handle;
  1322.           80 local drive.                     }
  1323.    dirHandle:=AL;
  1324.    status:=AH;
  1325.    If dirHandle=0
  1326.     then begin status:=0;Result:=$FF end {INVALID_DRIVE_NUMBER}
  1327.     else Result:=0;
  1328.    GetDirectoryHandle:=(Result=0)
  1329.    end;
  1330. { result: $00 success; $FF Invalid Drive Number }
  1331. end;
  1332.  
  1333.  
  1334. {F216/00 [2.15c+]}
  1335. Function SetDirectoryHandle( sourceDirHandle:Byte; sourceDirPath:String;
  1336.                              targetDirHandle:Byte ):boolean;
  1337. { make handle 'targetHandle' point to the directory provided by
  1338.   sourceHandle and/or sourceDirPath. ( "Volume:dir\subdir" )   }
  1339. Type Treq=record
  1340.           len       :word;
  1341.           subFunc   :byte;
  1342.           _TargetDH :Byte;
  1343.           _SourceDH :Byte;
  1344.           _SourceDP :String[255]
  1345.           end;
  1346.     TPreq=^Treq;
  1347. Var p:Byte;
  1348. Begin
  1349. WITH TPreq(GlobalReqBuf)^
  1350.  do begin
  1351.     subFunc:=$00;
  1352.     _TargetDH:=targetDirHandle;
  1353.     _SourceDH:=SourceDirHandle;
  1354.     if SourceDirHandle=0
  1355.      then ConvertPathToVolFormat(SourceDirPath);
  1356.     _sourceDP:=sourceDirPath;
  1357.     UpString(_sourceDP);
  1358.     len:=4+ord(_SourceDP[0]);
  1359.     F2SystemCall($16,len+2,0,result);
  1360.     end;
  1361. SetDirectoryHandle:=(result=0)
  1362. { resultcodes:
  1363.   00 Success; 98h Volume does not exist;
  1364.   9Bh Bad directory handle; 9Ch Invalid Path. }
  1365. end;
  1366.  
  1367.  
  1368. {F216/12 [2.15c+]}
  1369. FUNCTION AllocPermanentDirHandle( DriveNumber:Byte;
  1370.                                   DirHandle : byte; DirPath : string ;
  1371.                               var NewDirHandle, EffectiveRights: byte ) :boolean;
  1372. { Effective server must be the server involved, i.e. where the dir is stored }
  1373. Type Treq=record
  1374.           len : word;
  1375.           subf : byte;
  1376.           _dirHandle : byte;
  1377.           _driveLetter : char;
  1378.           _DirectoryPath: String[255];
  1379.           end;
  1380.      Trep=record
  1381.           _newDirHandle : byte;
  1382.           _EffectiveRights : byte; { e.r. mask }
  1383.           end;
  1384.      TPreq=^Treq;
  1385.      TPrep=^Trep;
  1386. Var p:Byte;
  1387. BEGIN
  1388. With TPreq(GlobalReqBuf)^
  1389.  do begin
  1390.     subf := $12;
  1391.     _dirHandle := dirHandle;
  1392.     _driveLetter := chr(DriveNumber+ord('A'));
  1393.     if Dirhandle=0
  1394.      then ConvertPathToVolFormat(DirPath);
  1395.     _DirectoryPath:=DirPath;
  1396.     UpString(_DirectoryPath);
  1397.     len:=4+ord(_DirectoryPath[0]);
  1398.     F2SystemCall($16,len+2,sizeof(Trep),result);
  1399.     end;
  1400. if result = 0
  1401.  then with TPrep(GlobalReplyBuf)^
  1402.       do begin
  1403.          effectiveRights := _effectiveRights;
  1404.          newDirHandle    := _newDirHandle;
  1405.          end;
  1406. AllocPermanentDirHandle:=(result=0);
  1407. { $00 Successful  $98 Volume doen't exist $9C Invalid path }
  1408. end;
  1409.  
  1410.  
  1411.  
  1412.  
  1413.  
  1414. {F216/13 [2.15c+]}
  1415. function AllocTemporaryDirHandle( DriveNumber:byte;
  1416.                              DirHandle : Byte; DirPath : String;
  1417.                          var NewDirHandle,EffectiveRights : Byte) : Boolean;
  1418. { Allocates a temporary directory handle, deleted automatically by EOJ. }
  1419. { Effective server must be the server involved, i.e. where the dir is stored }
  1420. Type TReq=record
  1421.           Len              : Word;
  1422.           SubF             : Byte;
  1423.           Handle           : Byte;
  1424.           Letter           : Char;
  1425.           _DirectoryPath   : String;
  1426.           end;
  1427.      TRep=record
  1428.           NewH    : Byte;
  1429.           Mask    : Byte;
  1430.           end;
  1431.      TPreq=^Treq;
  1432.      TPrep=^Trep;
  1433. Var p:Byte;
  1434. begin
  1435. with TPReq(GlobalReqBuf)^
  1436.  do begin
  1437.     SubF    := $13;
  1438.     Handle  := DirHandle;
  1439.     Letter  := chr(DriveNumber+ord('A'));
  1440.    { Allocating handles requires paths to be in
  1441.       the VOL:path format.. NOT canonical }
  1442.     if handle=0
  1443.      then ConvertPathToVolFormat(DirPath);
  1444.     _DirectoryPath:=DirPath;
  1445.     UpString(_DirectoryPath);
  1446.     Len:=4+length(_DirectoryPath);
  1447.     F2SystemCall($16,len+2,SizeOf(Trep),result);
  1448.     end;
  1449. with TPrep(GlobalReplyBuf)^
  1450.  do begin
  1451.     NewDirHandle    := NewH;
  1452.     EffectiveRights := Mask;
  1453.     end;
  1454. AllocTemporaryDirHandle:=(result=0);
  1455. { result: 00 success; 98h Volume doesn't exist; 9Ch Invalid Path }
  1456. end;
  1457.  
  1458.  
  1459. {F216/14 [2.15c+]}
  1460. function DeallocateDirHandle(DirHandle : Byte) : Boolean;
  1461. { This function deletes a directory handle }
  1462. Type TReq=record
  1463.           Len    : Word;
  1464.           SubF   : Byte;
  1465.           Handle : Byte;
  1466.           end;
  1467.      TPreq=^Treq;
  1468. begin
  1469. with TPReq(GlobalReqBuf)^
  1470.  do begin
  1471.     Len   := 2;
  1472.     SubF  := $14;
  1473.     Handle:= DirHandle;
  1474.     end;
  1475. F2SystemCall($16,Sizeof(Treq),0,result);
  1476. DeallocateDirHandle:=(result=0);
  1477. { result:
  1478.   00h  - Success; 9Bh  - Bad directory handle }
  1479. end;
  1480.  
  1481.  
  1482. {E901 }
  1483. Function GetSearchDriveVector(Var vector:TsearchDriveVector):boolean;
  1484. Var regs:TTregisters;
  1485.     tmp1,tmp2:word;
  1486. begin
  1487. regs.ax:=$E901;
  1488. GetGlobalBufferAddress(tmp1,tmp2,regs.ds,regs.dx);
  1489. { DS:DX real-mode address of GlobalReplyBuffer }
  1490. RealModeIntr($21,regs);
  1491. result:=0;
  1492. Move(GlobalReplyBuf^,vector,sizeof(TsearchDriveVector));
  1493. vector[17]:=$FF;
  1494. GetSearchDriveVector:=True;
  1495. end;
  1496.  
  1497. {E902 }
  1498. Function SetSearchDriveVector(vector:TsearchDriveVector):boolean;
  1499. Var regs:TTregisters;
  1500.     tmp1,tmp2:word;
  1501. begin
  1502. regs.ax:=$E902;
  1503. Move(vector,GlobalReqBuf^,sizeof(TsearchDriveVector));
  1504. GetGlobalBufferAddress(regs.ds,regs.dx,tmp1,tmp2);
  1505. { DS:DX real-mode address of GlobalRequestBuffer }
  1506. RealModeIntr($21,regs);
  1507. result:=0;
  1508. SetSearchDriveVector:=True;
  1509. end;
  1510.  
  1511. Function IsSearchDrive(DriveNumber:byte):boolean;
  1512. Var pth:string;
  1513. begin
  1514. IsSearchDrive:=(getEnvPath(pth)
  1515.                and (pos(chr(DriveNumber+ord('A'))+':',pth)>0));
  1516. end;
  1517.  
  1518.  
  1519. {E905 (shell 3.00+)}
  1520. Function MapFakeRootDirectory(DriveNumber:byte; DirPath:string):boolean;
  1521. { Dirpath may include server and volumename }
  1522. Var regs:TTregisters;
  1523.     tmp1,tmp2:word;
  1524.     PName:string;
  1525. begin
  1526. with regs
  1527.  do begin
  1528.     ax:=$E905;
  1529.     bl:=driveNumber+1;  { FF default, 0=A, 2= B etc. }
  1530.     GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
  1531.     { VLM patch for SERVER/VOL: and VOL: type paths }
  1532.     if (DirPath[0]>#2) and (pos(':',DirPath)>2)
  1533.      then GetTrueEntryName(DirPath,PName)
  1534.      else PName:=DirPath;
  1535.     Pname:=Pname+#0;
  1536.     move(PName[1],GlobalReqBuf^,ord(PName[1]));
  1537.     { DS:DX real-mode address of GlobalRequestBuffer holding new path }
  1538.     RealModeIntr($21,regs);
  1539.     if (flags and 1 {carry})>0
  1540.      then result:=al
  1541.      else result:=0;
  1542.     end;
  1543. MapFakeRootDirectory:=(result=0);
  1544. { $00 Successful $03 Invalid path $0F Invalid Drive $11 Not same device }
  1545. end;
  1546.  
  1547. {E906 (shell 3.00+)}
  1548. Function DeleteFakeRootDirectory(DriveNumber:byte):boolean;
  1549. Var regs:TTregisters;
  1550. begin
  1551. with regs
  1552.  do begin
  1553.     ax:=$E906;
  1554.     bl:=DriveNumber+1;
  1555.     RealModeIntr($21,regs);
  1556.     result:=0;
  1557.     end;
  1558. DeleteFakeRootDirectory:=(result=0);
  1559. end;
  1560.  
  1561. {E907 (shell 3.00+)}
  1562. Function GetRelativeDriveDepth(DriveNumber:byte; Var depth:byte):boolean;
  1563. Var regs:TTregisters;
  1564. begin
  1565. with regs
  1566.  do begin
  1567.     ax:=$E907;
  1568.     bl:=DriveNumber+1;
  1569.     RealModeIntr($21,regs);
  1570.     depth:=al;
  1571.     if al<$FF
  1572.      then result:=0
  1573.      else result:=$FF; { no fake root assigned }
  1574.     end;
  1575. GetRelativeDriveDepth:=(result=0);
  1576. { 00 Succesful $FF No fake root assigned }
  1577. end;
  1578.  
  1579. {secondary}
  1580. Function DeleteDriveMapping(DriveNumber:Byte):boolean;
  1581. Var dirHandle,status:byte;
  1582.     pth:string;
  1583.     ch:char;
  1584.     p:byte;
  1585.     DDepth,Dflag:byte;
  1586. begin
  1587. { if searchdrive, remove drive from searchtable and PATH environment string }
  1588. IF GetEnvPath(pth)
  1589.  then begin
  1590.       if pth[ord(pth[0])]<>';'
  1591.        then pth:=pth+';';
  1592.       p:=pos(chr(DriveNumber+ord('A'))+':',pth);
  1593.       if p>0
  1594.        then begin { it is a searchdrive, remove from path }
  1595.             Repeat
  1596.              ch:=pth[p];
  1597.              delete(pth,p,1);
  1598.             UNTIL ch=';';
  1599.             SetEnvPath(pth); { also creates a new searchdriveVector }
  1600.             end;
  1601.       end;
  1602. IF (result=0) and GetDirectoryHandle(DriveNumber,dirHandle,status)
  1603.  then begin
  1604.       IF GetRelativeDriveDepth(DriveNumber,DDepth) { is it a fake root ? }
  1605.        then DeleteFakeRootDirectory(DriveNumber);
  1606.       GetDriveFlag(DriveNumber,Dflag);
  1607.       SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_UNUSED);
  1608.       SetDriveHandle(DriveNumber,0);
  1609.       SetDriveConnectionId(DriveNumber,0);
  1610.       DeallocateDirHandle(dirHandle);
  1611.       end;
  1612. DeleteDriveMapping:=(result=0);
  1613. end;
  1614.  
  1615.  
  1616. {secondary }
  1617. FUNCTION MapPermanentDrive(DriveNumber:byte; DirectoryPath:string;
  1618.                            Root:boolean):boolean;
  1619. var pth        : string;
  1620.     DriveHandle: Byte;
  1621. begin
  1622. IF GetTrueEntryName(DirectoryPath,pth)
  1623.  then begin
  1624.       while pth[ord(pth[0])] IN ['\','.','*','?']
  1625.        do dec(pth[0]);
  1626.       if pth[1]<>'\'
  1627.        then result:=$104 { attempt to map network drive to local drive }
  1628.        else begin
  1629.             If GetDriveHandle(DriveNumber,DriveHandle) and (DriveHandle<>0)
  1630.              then DeleteDriveMapping(DriveNumber);
  1631.  
  1632.             IF MapFakeRootDirectory(DriveNumber,pth)
  1633.              then begin
  1634.                   if (not root)
  1635.                    then DeleteFakeRootDirectory(DriveNumber);
  1636.                     { does not delete the mapping itself,
  1637.                       only the fake root. }
  1638.                   end;
  1639.             end;
  1640.       end
  1641.  else result:=$101; { direcory not locatable }
  1642. MapPermanentDrive:=(result=0);
  1643. end;
  1644.  
  1645. {secondary}
  1646. FUNCTION MapDrive(DriveNumber:Byte; DirectoryPath:string;
  1647.                   Root, Permanent:boolean):boolean;
  1648. var rights      : byte;
  1649.     newHandle   : byte;
  1650.     HandlePth,pth,srvr,vol: string;
  1651.     OldConnId,VolConnId:byte;
  1652.     p:byte;
  1653.     VolNbr:byte;
  1654.     Dflag:byte;
  1655. begin
  1656. IF Permanent
  1657.  then begin
  1658.       MapDrive:=MapPermanentDrive(DriveNumber,DirectoryPath,Root);
  1659.       exit;
  1660.       end;
  1661. { map temporary drive }
  1662. IF GetTrueEntryName(DirectoryPath,pth)
  1663.  then begin
  1664.       if pth[ord(pth[0])]<>'\'
  1665.        then pth:=pth+'\';
  1666.       if pth[1]<>'\'
  1667.        then result:=$104 { attempt to map network drive to local drive }
  1668.        else begin
  1669.             delete(pth,1,2);
  1670.             p:=pos('\',pth);
  1671.             if p=0 then result:=$106;
  1672.             srvr:=copy(pth,1,p-1);
  1673.             delete(pth,1,p);
  1674.             p:=pos('\',pth);
  1675.             if p=0 then result:=$105; { volume does not exist }
  1676.             vol:=copy(pth,1,p-1);
  1677.             delete(pth,1,p);
  1678.             IF NOT GetConnectionId(srvr,VolConnId)
  1679.              then result:=$106; { server does not exist }
  1680.             end;
  1681.       end
  1682.  else result:=$101; { direcory not locatable }
  1683. if (result=0)
  1684.  then begin
  1685.       while pth[ord(pth[0])] IN ['\','.','*','?']
  1686.        do dec(pth[0]);
  1687.  
  1688.       { rebuild path: Alloc handle requires VOL:path format }
  1689.       HandlePth:=vol+':\'+pth;
  1690.       GetPreferredConnectionId(OldConnId);
  1691.       SetPreferredConnectionId(VolConnId);
  1692.  
  1693.      { IF Permanent
  1694.        then AllocPermanentDirHandle(DriveNumber,0,HandlePth,
  1695.                                     newHandle,rights)
  1696.        else}
  1697.       AllocTemporaryDirHandle(DriveNumber,0,HandlePth,
  1698.                                     newHandle,rights);
  1699.       if (result=0)
  1700.        then begin
  1701.             GetDriveFlag(DriveNumber,Dflag);
  1702.             {If Permanent
  1703.              then SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_PERMANENT)
  1704.              else}
  1705.             SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_TEMPORARY);
  1706.             SetDriveHandle(DriveNumber,newHandle);
  1707.             SetDriveConnectionId(DriveNumber,VolConnId);
  1708.             IF root
  1709.              then MapFakeRootDirectory(DriveNumber,'\\'+srvr+'\'+vol+'\'+pth);
  1710.             end;
  1711.       SetPreferredConnectionId(OldConnId);
  1712.       end;
  1713. MapDrive:=(result=0);
  1714. end;
  1715.  
  1716.  
  1717.  
  1718. Function MapSearchDrive(DriveNumber:byte; DirPath:string;
  1719.                         PathPosition:byte;
  1720.                         Insert,Root,Permanent:Boolean):boolean;
  1721. Var pth:string;
  1722.     p,scCount:byte;
  1723.     ch:char;
  1724. begin
  1725. IF MapDrive(DriveNumber,DirPath,Root,Permanent)
  1726.  then begin
  1727.       GetEnvPath(pth);
  1728.       if pth[ord(pth[0])]<>';'
  1729.        then pth:=pth+';';
  1730.       scCount:=1;p:=1;
  1731.       while (scCount<PathPosition) and (p<=ord(pth[0]))
  1732.        do begin
  1733.           if pth[p]=';'
  1734.            then inc(scCount);
  1735.           inc(p);
  1736.           end;
  1737.       { pth[p] is first character of PathPositions' entry in path }
  1738.       If p<ord(pth[0])
  1739.        then begin
  1740.             IF (Not Insert)
  1741.              then Repeat
  1742.                   ch:=pth[p];
  1743.                   delete(pth,P,1);
  1744.                   UNTIL (ch=';') or (p>=ord(pth[0]));
  1745.             pth:=copy(pth,1,p-1)+chr(DriveNumber+ord('A'))
  1746.                        +':.;'+copy(pth,p,255);
  1747.             end
  1748.        else pth:=pth+chr(DriveNumber+ord('A'))+':.;';
  1749.       SetEnvPath(pth);
  1750.       end;
  1751. MapSearchDrive:=(result=0);
  1752. end;
  1753.  
  1754. {secondary}
  1755. Function DeleteConnectionsDriveMappings(ConnId:Byte):Boolean;
  1756. Var t,connId2,res:Byte;
  1757. begin
  1758. res:=$FF;
  1759. for t:=0 to 31
  1760.  do if GetDriveConnectionId(t,connId2) and (connId2=connId)
  1761.      then begin
  1762.           DeleteDriveMapping(t);
  1763.           if result=0
  1764.            then res:=0;
  1765.           end;
  1766. result:=res;
  1767. DeleteConnectionsDriveMappings:=(result=0);
  1768. {00 successful  FF No mappings affected OR Invalid connectionId }
  1769. end;
  1770.  
  1771.  
  1772. {4409 / implemented as a secondary function }
  1773. Function IsNetworkDrive(driveNumber:Byte):boolean;
  1774. { isNetworkDrive is set to TRUE if the drive is a) a network drive, and
  1775.   b) a legal drive letter was used.                                         }
  1776. Var regs:TTRegisters;
  1777. begin
  1778. With regs
  1779. do begin
  1780.    AX:=$4409;
  1781.    BL:=DriveNumber+1;
  1782.    RealModeIntr($21,Regs);
  1783.    IsNetworkDrive:=(DX and $1000)<>0
  1784.    end;
  1785. end;
  1786.  
  1787.  
  1788. {--======================-- Entries --===============================--}
  1789.  
  1790.  
  1791. {60.. (extended DOS call)}
  1792. Function GetTrueEntryName(DirPath:string; Var CanonicalPath:string):boolean;
  1793. { SERVER/VOL:[\]Path   -> \\SERVER\VOL\path
  1794.   VOL:[\]Path          -> \\effective_server_name\VOL\path
  1795.   D:\                  -> D:\.
  1796.  
  1797. { if a volumename is supplied without a servername, the name of the
  1798.   effective server will be returned. }
  1799.  
  1800. { Format of returned string:
  1801.   a) D:\path\file.ext or
  1802.   b) \\servername\volumename\path\file.ext }
  1803.  
  1804. LABEL skip;
  1805.  
  1806. Var reply  :array[1..128] of byte;
  1807.     regs   :TTregisters;
  1808.     pcolon,
  1809.     pslash :byte;
  1810.     srvr,
  1811.     volname:string[47];
  1812.     connId :Byte;
  1813. begin
  1814. { ----- Pre processing }
  1815. if DirPath[0]>#2
  1816.  then begin
  1817.       if ((DirPath[1]='\') and (DirPath[2]='\'))
  1818.        then begin
  1819.             CanonicalPath:=DirPath;
  1820.             UpString(Canonicalpath);
  1821.             goto skip
  1822.             end;
  1823.       pcolon:=pos(':',DirPath);
  1824.       if (pcolon=2) and (DirPath[0]=#3) and (DirPath[3]='\')
  1825.        then DirPath:=DirPath+'.';
  1826.       { fix known problem of netware: D:\. instead of D:\ }
  1827.       if (pcolon=2) and (DirPath[0]=#2)
  1828.        then DirPath:=DirPath+'.';
  1829.       { fix know problem of -among others- OS/2-dos: D:. instead of D: }
  1830.       end;
  1831. pcolon:=pos(':',DirPath);
  1832. if pcolon>2
  1833.  then begin { format must be VOL:[\]path or SERVER/VOL:[\]Path }
  1834.       pslash:=pos('/',DirPath);
  1835.       if pslash=0
  1836.        then pslash:=$FF;
  1837.       if (pslash<pcolon)
  1838.        then begin { SERVER/VOL: }
  1839.             srvr:=copy(DirPath,1,pslash-1);
  1840.             delete(DirPath,1,pslash);
  1841.             pcolon:=pos(':',DirPath);
  1842.             end
  1843.        else begin { VOL: }
  1844.             GetEffectiveConnectionId(connId);
  1845.             GetFileServerName(connId,srvr);
  1846.             end;
  1847.       volname:=copy(dirPath,1,pcolon-1);
  1848.       delete(dirPath,1,pcolon);
  1849.       if (dirPath[0]>#0) and (dirPath[1]='\')
  1850.         then delete(DirPath,1,1);
  1851.       DirPath:='\\'+srvr+'\'+volname+'\'+DirPath;
  1852.       end;
  1853. if dirPath=''
  1854.  then dirPath:='\';
  1855. { ----- actual call }
  1856. dirPath:=dirPath+#0;   { zero terminate }
  1857. WITH regs
  1858.  do begin
  1859.     Move(dirPath[1],GlobalReqBuf^,ord(dirPath[0]));
  1860.     GetGlobalBufferAddress(ds,si,es,di);
  1861.     { DS:SI real mode pointer to GlobalRequestBuffer holding asciiz path ;
  1862.       ES:DI real mode pointer to GlbalReplyBuffer }
  1863.     ah:=$60;
  1864.     RealModeIntr($21,regs);
  1865.     Move(GlobalReplyBuf^,reply[1],128);
  1866.     if (regs.flags and 1 {carry})>0
  1867.      then begin
  1868.           result:=ax;
  1869.           reply[1]:=0;
  1870.           end
  1871.      else result:=0;
  1872.     end;
  1873. ZstrCopy(CanonicalPath,reply[1],128);
  1874. { ----- post-processing -- strip \ and . }
  1875. skip: ;
  1876. While CanonicalPath[ord(CanonicalPath[0])] in ['\','.']
  1877.  do dec(CanonicalPath[0]);
  1878. GetTrueEntryName:=(result=0);
  1879. { $00  successful
  1880.   $02 Invalid component in directory path OR drive letter only
  1881.   $03 Malformed path OR invalid drive letter                    }
  1882. end;
  1883.  
  1884.  
  1885.  
  1886. {3B.. }
  1887. Function ChangeDirectory(DirPath:string):boolean;
  1888. { does not change the default drive }
  1889. Var regs:TTregisters;
  1890.     tmp1,tmp2:word;
  1891. begin
  1892. if DirPath[0]>#63
  1893.  then result:=$110 { length of path too long }
  1894.  else begin
  1895.       DirPath:=DirPath+#0;
  1896.       with regs
  1897.        do begin
  1898.           ah:=$3b;
  1899.           Move(DirPath[1],GlobalReqBuf^,ord(DirPath[0]));
  1900.           GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
  1901.           { DS:DX real-mode pointer to GlobalRequestBuffer holding DirPath }
  1902.           RealModeIntr($21,regs);
  1903.           If (flags and 1 {carry})>0
  1904.            then result:=$111 { invalid pathname }
  1905.            else result:=0;
  1906.           end;
  1907.       end;
  1908. ChangeDirectory:=(result=0);
  1909. end;
  1910.  
  1911. {F216/0A [2.15+]}
  1912. Function CreateDirectory(DirHandle:Byte; DirPath:string; MaxRightsMask:byte):boolean;
  1913. Type Treq=record
  1914.           len       :word;
  1915.           subFunc   :byte;
  1916.           _DirHandle:byte;
  1917.           _MRM      :byte;
  1918.           _dirPath  :string[255];
  1919.           end;
  1920.      TPreq=^Treq;
  1921. Begin
  1922. WITH TPreq(GlobalreqBuf)^
  1923. do begin
  1924.    subFunc:=$0A;
  1925.    _dirHandle:=DirHandle;
  1926.    _MRM:=MaxRightsMask;
  1927.    _DirPath:=DirPath;
  1928.    len:=4+ord(_dirPath[0]);
  1929.    F2SystemCall($16,len+2,0,result);
  1930.    end;
  1931. CreateDirectory:=(result=0)
  1932. { 00 successful   84 No create privileges  98 Volume doesn't exist
  1933.   FF directory already exists }
  1934. end;
  1935.  
  1936.  
  1937. {F216/0B [2.15c+]}
  1938. Function DeleteDirectory(DirHandle:Byte; DirPath:string):boolean;
  1939. Type Treq=record
  1940.           len       :word;
  1941.           subFunc   :byte;
  1942.           _DirHandle:byte;
  1943.           unused    :byte;
  1944.           _DirPath  :string[255];
  1945.           end;
  1946.      TPreq=^Treq;
  1947. Begin
  1948. WITH TPreq(GlobalreqBuf)^
  1949. do begin
  1950.    subFunc:=$0B;
  1951.    _DirHandle:=DirHandle;
  1952.    _DirPath:=DirPath;
  1953.    unused:=0;
  1954.    len:=4+ord(_DirPath[0]);
  1955.    F2SystemCall($16,len+2,0,result);
  1956.    end;
  1957. DeleteDirectory:=(result=0)
  1958. { 00 successful            8A No delete privileges
  1959.   98 Volume doesn't exist  9B Bad directory handle
  1960.   9C Invalid path          9F Directory in use
  1961.   A0 Directory not empty }
  1962. end;
  1963.  
  1964.  
  1965. {F217/F4 [3.0+]}
  1966. Function ConvertPathToDirEntryId(dirHandle:Byte; dirPath:string;
  1967.                              Var VolNbr    :byte;
  1968.                              Var dirEntryID:LongInt):boolean;
  1969. { aka ConvertPathToDirEntry }
  1970. Type Treq=record
  1971.           len       :word;
  1972.           subFunc   :byte;
  1973.           _dirHandle:byte;
  1974.           _DirPath  :string[255];
  1975.           end;
  1976.      Trep=record
  1977.           _volNbr:Byte;
  1978.           _EntryId:Longint; {hi-lo}
  1979.           end;
  1980.      TPreq=^Treq;
  1981.      TPrep=^Trep;
  1982. Begin
  1983. WITH TPreq(GlobalReqBuf)^
  1984. do begin
  1985.    subFunc:=$F4;
  1986.    _dirHandle:=DirHandle;
  1987.    _dirPath:=DirPath;
  1988.    UpString(_DirPath);
  1989.    If DirHandle=0
  1990.     then ConvertPathToVolFormat(_DirPath);
  1991.    len:=3+ord(_DirPath[0]);
  1992.    F2SystemCall($17,len+2,SizeOf(Trep),result);
  1993.    end;
  1994. With TPrep(GlobalReplyBuf)^
  1995. do begin
  1996.    VolNbr    :=_volNbr;
  1997.    dirEntryId:=_EntryId;
  1998.    end;
  1999. ConvertPathToDirEntryId:=(result=0)
  2000. { 00 Successful        9B Bad directory Handle
  2001.   9C Invalid Path      C6 No console rights }
  2002. end;
  2003.  
  2004. {F217/F3 [3.0+]}
  2005. Function MapDirEntryIdToPath(VolNbr:byte;DirEntryId:Longint; NStype:byte;
  2006.                              Var ExtPath:string):boolean;
  2007. {aka MapDirectoryNumberToPath }
  2008. { Returns full path/ with nameSpace information;
  2009.   Doesn't return server or volumename. }
  2010. Type Treq=record
  2011.           len     :word;
  2012.           subFunc :byte;
  2013.           _VolNbr :byte;
  2014.           _EntryId:longint; {hi-lo}
  2015.           _NameSp :byte;
  2016.           end;
  2017.      Trep=record
  2018.           _path:array[1..255] of byte; {!! maximum: 512 bytes in path ! }
  2019.           end;
  2020.      TPreq=^Treq;
  2021.      TPrep=^Trep;
  2022. Var TempPath:string;
  2023. Begin
  2024. WITH TPreq(GlobalReqBuf)^
  2025.  do begin
  2026.     len:=SizeOf(Treq)-2;
  2027.     subFunc:=$F3;
  2028.     _VolNbr:=VolNbr;
  2029.     _EntryId:=DirEntryId;
  2030.     _NameSp:=NStype;
  2031.     end;
  2032. F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
  2033. if result=0
  2034.  then begin
  2035.       With TPrep(GlobalReplyBuf)^
  2036.        do ZstrCopy(TempPath,_path,255);
  2037.       { TempPath according to the 'new' Novell format;
  2038.         translate into a 'DOS' style path }
  2039.       NovPath2DOSPath(TempPath,ExtPath); { dir\subdir (no server or volume name) }
  2040.       end;
  2041. MapDirentryIdtoPath:=(result=0)
  2042. { 00 Successful   C6 No console rights  FF ? }
  2043. end;
  2044.  
  2045.  
  2046. {F216/02}
  2047. Function ScanDirectoryInformation(dirHandle:byte; searchDirPath:string;
  2048.                             {i/o} Var sequenceNumber:word;
  2049.                            {out:} Var dirInfo:Tentry    ):boolean;
  2050. { set sequenceNumber to 0 before the first call.
  2051.  
  2052.   If wildcards (* or ?) are included in the searchDirPath:
  2053.   Iterate until a $9C error is returned.
  2054.  
  2055.   If you don't include a wildcard in the searchDirPath, only use
  2056.   this call once. Do not iterate, the same entry will be returned
  2057.   eternaly.
  2058.  
  2059.   }
  2060. Type Treq=record
  2061.           len          :word;
  2062.           subFunc      :byte;
  2063.           _dirHandle   :byte;
  2064.           _subDirNumber:word; {hi-lo}
  2065.           _dirPath     :string[255]
  2066.           end;
  2067.      Trep=record
  2068.           _subDirName   :array[1..16] of byte;
  2069.           _creationDate :word;
  2070.           _creationTime :word;
  2071.           _ownerObjId   :LongInt; {hi-lo}
  2072.           _maxRightsMask:word;
  2073.           _SubDirNbr    :word; {hi-lo}
  2074.           end;
  2075.      TPreq=^Treq;
  2076.      TPrep=^Trep;
  2077. Begin
  2078. WITH TPreq(GlobalReqBuf)^
  2079.  do begin
  2080.     subFunc:=$02;
  2081.     _dirHandle:=dirHandle;
  2082.     _subDirNumber:=swap(sequenceNumber); { force hi-lo}
  2083.     _dirPath:=searchDirPath;
  2084.     UpString(_dirPath);
  2085.     len:=5+ord(searchDirPath[0]);
  2086.     F2SystemCall($16,len+2,SizeOf(Trep),result);
  2087.     end;
  2088. With TPrep(GlobalReplyBuf)^
  2089.  do begin
  2090.     FillChar(dirInfo,SizeOf(Tentry),0);
  2091.     ZstrCopy(dirInfo.EntryName,_SubDirName,16);
  2092.  
  2093.     DosTime2NovTime(MakeLong(swap(_CreationDate),swap(_CreationTime)),
  2094.                     dirInfo.creationTime);
  2095.     dirInfo.ownerId:=Lswap(_ownerObjId);
  2096.     dirInfo.RightsMask:=_maxRightsMask;
  2097.     sequenceNumber:=swap(_SubDirNbr)+1;
  2098.     end;
  2099. ScanDirectoryInformation:=(result=0)
  2100. {resultcodes: $00 success;  $98 Volume does not exist;
  2101.               $9B Bad directory Handle $9C Invalid Path }
  2102. end;
  2103.  
  2104.  
  2105. {F216/0F [2.0/2.1/3.x]}
  2106. Function RenameDirectory( dirHandle:Byte; dirPath, newDirName :String):Boolean;
  2107. { The new directory name must be a regular (legal) directory name,
  2108.   max 14 chars long.
  2109.   The user must have Parental and Modify rights in the parent directory of
  2110.   the directory to be renamed.                                            }
  2111. Type Treq=record
  2112.           len         :word;
  2113.           subFunc     :byte;
  2114.           _dirHandle  :Byte;
  2115.           _dirNames   :Array[0..255+1+14] of byte; { _dirpath[0] is allowed to be 0 }
  2116.           end;
  2117.      TPreq=^Treq;
  2118. Begin
  2119. WITH TPreq(GlobalReqBuf)^
  2120.  do begin
  2121.     subFunc:=$0F;
  2122.     _dirHandle:=dirHandle;
  2123.     Upstring(dirPath);
  2124.     UpString(newDirName);
  2125.     Move(DirPath[0],_DirNames[0],ord(DirPath[0])+1);
  2126.     Move(newDirName[0],_DirNames[1+_DirNames[0]],ord(newDirName[0])+1);
  2127.     len:=4+ord(dirPath[0])+ord(newDirName[0]);
  2128.     F2SystemCall($16,len+2,0,result);
  2129.     end;
  2130. RenameDirectory:=(result=0)
  2131. { Possible ResultCodes:
  2132.   8B No Rename Privileges; 9B Bad Directory Handle;
  2133.   9C Invalid Path; 9E Invalid (new) Dir Name.                                  }
  2134. end;
  2135.  
  2136.  
  2137. {F216/1F [2.15c+]}
  2138. Function GetDirectoryEntry(DirHandle:byte;
  2139.                        Var dirEntry:Tentry):boolean;
  2140. Type Treq=record
  2141.           len:word;
  2142.           subFunc:byte;
  2143.           _dirHandle:byte;
  2144.           end;
  2145.      Trep=record
  2146.           _Entry       :TintEntry;
  2147.           end;
  2148.      TPreq=^Treq;
  2149.      TPrep=^Trep;
  2150. Begin
  2151. WITH TPreq(GlobalReqBuf)^
  2152.  do begin
  2153.     len:=SizeOf(Treq)-2;
  2154.     subFunc:=$1F;
  2155.     _dirHandle:=dirHandle;
  2156.     end;
  2157. F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
  2158. With TPrep(GlobalReplyBuf)^
  2159.  do begin
  2160.     Convert2ExtEntry(_entry,dirEntry);
  2161.     end;
  2162. GetDirectoryEntry:=(result=0)
  2163. { 00 successful            98 Volume doesn't exist
  2164.   9B Bad directory handle  9C Invalid path           }
  2165. end;
  2166.  
  2167.  
  2168. {B601 [2.0+] }
  2169. function SetExtendedFileAttributes(FilePath:String; Attr:Byte) : Boolean;
  2170. { See GetExtFAttr for meaning of Attr the Attribute
  2171.   Function result code:
  2172.     00h Success;
  2173.     FFh File not found;
  2174.     FEh Access denied }
  2175. Var Novregs:TTRegisters;
  2176.     tmp1,tmp2:word;
  2177. begin
  2178. with NovRegs
  2179. do begin
  2180.    AX := $B601;
  2181.    if FilePath[0]=#255
  2182.     then FilePath[255]:=#0
  2183.     else FilePath:=FilePath+#0;
  2184.    Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
  2185.    GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
  2186.    { DS:DX real mode pointer to GlobalRequestBuffer holding FilePath }
  2187.    CL := Attr;
  2188.    RealModeIntr($21,NovRegs);
  2189.    IF (Flags AND 1 {carry})>0
  2190.     then Result:=AL
  2191.     else Result:=$00;
  2192.    Result := AL
  2193.    end;
  2194. SetExtendedFileAttributes:=(Result=0);
  2195. end;
  2196.  
  2197.  
  2198.  
  2199. {B600 [2.0+]}
  2200. function GetExtendedFileAttributes(FilePath:String; var Attributes:Byte) : Boolean;
  2201. { Meaning of Attributes:
  2202.   7   6   5   4   3   2   1   0
  2203.   |   |   |   |       |   |   |
  2204.   |   |   |   |       +---+---+------Search mode
  2205.   |   |   |   +----------------------transactional bit  A_TRANSACTIONAL
  2206.   |   |   +--------------------------Indexing bit       A_INDEXED
  2207.   |   +------------------------------Read Audit bit     A_READ_AUDIT
  2208.   +----------------------------------Write Audit bit    A_WRITE_AUDIT
  2209.  }
  2210. Var NovRegs:TTRegisters;
  2211.     tmp1,tmp2:word;
  2212. begin
  2213. with NovRegs
  2214. do begin
  2215.    AX := $B600;
  2216.    if FilePath[0]=#255
  2217.     then FilePath[255]:=#0
  2218.     else FilePath:=FilePath+#0; { null terminate string }
  2219.    Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
  2220.    GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
  2221.    { DS:DX real mode pointer to GlobalRequestBuffer hloding FilePath }
  2222.    RealModeIntr($21,NovRegs);
  2223.    IF (Flags and 1 {carry})>0
  2224.     then Result := AL
  2225.     else Result:=$00;
  2226.    Attributes := CL;
  2227.    end;
  2228. GetExtendedFileAttributes:=(Result=0);
  2229. { $8C caller lacks privileges
  2230.   FEh not permitted to search directory
  2231.   FFh file not found }
  2232. end;
  2233.  
  2234.  
  2235.  
  2236.  
  2237. {F3.. [2.x/3.x]}
  2238. Function FileServerFileCopy( sourceFileHandle, destFileHandle:word;
  2239.                              sourceFileOffset, destFileOffset:Longint;
  2240.                              numberOfBytesToCopy :Longint;
  2241.                          VAR numberOfBytesCopied :Longint       ):boolean;
  2242. {Note:    both source and destination must be on the same file server
  2243. SeeAlso: 3C..,3F..}
  2244. Type Treq=record
  2245.         _sFH,_dFH      :word;    {lo-hi} {as returned by GetFileHandle.}
  2246.         _sFoffs,_dfOffs:Longint; {lo-hi}
  2247.         _NbrOfBytes    :Longint; {lo-hi}
  2248.         end;
  2249.      TPreq=^Treq;
  2250. Var regs:TTRegisters;
  2251.     tmp1,tmp2:word;
  2252. begin
  2253. with TPreq(GlobalReqBuf)^
  2254.  do begin
  2255.     _sFH:=sourceFileHandle;
  2256.     _dFH:=destFileHandle;
  2257.     _sFoffs:=sourceFileOffset;
  2258.     _dFoffs:=destFileOffset;
  2259.     _NbrOfBytes:=numberOfBytesToCopy;
  2260.     end;
  2261. with regs
  2262.  do begin
  2263.     AH:=$F3;
  2264.     GetGlobalBufferAddress(es,di,tmp1,tmp2);
  2265.     { ES:DI real mode pointer to GlobalRequestBuffer }
  2266.     RealModeIntr($21,regs);
  2267.     result:=AL;
  2268.     end;
  2269. numberOfBytesCopied:=MakeLong(regs.cx,regs.dx); { ? swap those regs for correct byte order ? }
  2270. FileServerFileCopy:=(Result=0);
  2271. end;
  2272.  
  2273. {level-0 function. See GetFileAttributes and SetFileAttributes }
  2274. Function DoFileAttributes(subf:byte;FilePath:string;VAR attr:byte):boolean;
  2275. Var regs:TTregisters;
  2276.     tmp1,tmp2:word;
  2277. begin
  2278. with regs
  2279. do begin
  2280.    AH:=$43;
  2281.    AL:=subf;
  2282.    if subf=$01 then CX:=attr;
  2283.    if filePath[0]=#255
  2284.     then filePath[255]:=#0
  2285.     else filePath:=filePath+#0;
  2286.    Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
  2287.    GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
  2288.    { DS:DX real mode pointer to GlobalRequestBuffer holding FilePath }
  2289.    RealModeIntr($21,regs);
  2290.    IF ((Flags and 1 {Fcarry})<>0)
  2291.     then result:=AL
  2292.     else begin
  2293.          result:=$00;
  2294.          if subf=$00 then attr:=CX
  2295.          end;
  2296.    end;
  2297. DoFileAttributes:=(result=$00);
  2298. { resultcodes: 00 success;        01 invalid function;
  2299.                03 path not found; 05 access denied. }
  2300. end;
  2301.  
  2302. {4300 [1.x/2.x/3.x]}
  2303. Function GetFileAttributes(FilePath:string; Var attr:byte):boolean;
  2304. { A_READ_ONLY,A_HIDDEN,A_SYSTEM and A_SHAREABLE only. }
  2305. begin
  2306. GetFileAttributes:=DoFileAttributes($00,FilePath,attr);
  2307. end;
  2308.  
  2309. {4301 [1.x/2.x/3.x]}
  2310. Function SetFileAttributes(FilePath:string; attr:byte):boolean;
  2311. { A_READ_ONLY,A_HIDDEN,A_SYSTEM and A_SHAREABLE only. }
  2312. Var _attr:byte;
  2313. begin
  2314. _attr:=attr;
  2315. SetFileAttributes:=DoFileAttributes($01,FilePath,_attr);
  2316. end;
  2317.  
  2318.  
  2319.  
  2320. {F217/0F [2.15c+]}
  2321. Function ScanFileInformation(DirHandle:Byte; FilePath:string;
  2322.                              SearchAttrib:Byte;
  2323.                         {i/o} VAR SequenceNbr:Integer;
  2324.                         {out} VAR fileInfo:Tentry):Boolean;
  2325. { To be called Iteratatively; initial value for seqNbr=-1 }
  2326. { wildcards in filename allowed.
  2327.   Iterate util an error $FF occurs }
  2328. Type Treq=record
  2329.           len          :word;
  2330.           subFunc      :byte;
  2331.           _seqNbr      :word; {hi-lo}
  2332.           _dirHandle   :byte;
  2333.           _searchAttrib:Byte;
  2334.           _filePath    :string;
  2335.           end;
  2336.      Trep=record
  2337.           _seqNbr      :word;    {hi-lo}
  2338.           _fileName    :array[1..14] of byte;
  2339.           _Fattr,
  2340.           _ExtFattr    :Byte;
  2341.           _Fsize       :LongInt; {hi-lo}
  2342.           _Crdate      :word;    {hi-lo}
  2343.           _LastAccDate :word;    {hi-lo}
  2344.           _LastUpdDate,
  2345.           _LastUpdTime :Word;
  2346.           _ownerObjId  :Longint; {hi-lo}
  2347.           _LastArchDate,
  2348.           _lastArchTime:Word;
  2349.           _reserved    :array[1..56] of byte;
  2350.           end;
  2351.      TPreq=^Treq;
  2352.      TPrep=^Trep;
  2353. Begin
  2354. WITH TPreq(GlobalReqBuf)^
  2355. do begin
  2356.    subFunc:=$0F;
  2357.    _seqNbr:=swap(word(SequenceNbr)); { force hi-lo }
  2358.    _dirHandle:=dirHandle;
  2359.    _searchAttrib:=searchAttrib;
  2360.    _filePath:=FilePath;
  2361.    len:=6+ord(_filePath[0]);
  2362.    F2SystemCall($17,len+2,SizeOf(Trep),result);
  2363.    end;
  2364. with TPrep(GlobalReplyBuf)^
  2365. do begin
  2366.    FillChar(fileInfo,sizeOf(fileInfo),#0);
  2367.    SequenceNbr:=Integer(swap(_seqNbr)); { force lo-hi }
  2368.    ZstrCopy(fileInfo.EntryName,_filename,15);
  2369.    fileInfo.Attributes:=(_ExtFattr SHL 8)+_Fattr;
  2370.    fileInfo.filesize:=Lswap(_Fsize);     { force lo-hi}
  2371.    fileinfo.OwnerID:=Lswap(_ownerObjID); { force lo-hi}
  2372.    DosTime2NovTime(MakeLong(swap(_CrDate),0),fileinfo.creationTime);
  2373.    DosTime2NovTime(MakeLong(swap(_LastAccDate),0),fileinfo.lastAccessTime);
  2374.    DosTime2NovTime(MakeLong(swap(_LastUpdDate),swap(_LastUpdTime))
  2375.                    ,fileinfo.ModifyTime);
  2376.    DosTime2NovTime(MakeLong(swap(_LastArchDate),swap(_lastArchTime))
  2377.                    ,fileinfo.ArchiveTime);
  2378.    end;
  2379. ScanFileInformation:=(result=0)
  2380. { 89 No search privileges  FF No more matching files }
  2381. end;
  2382.  
  2383.  
  2384. {F217/10 [2.15c+]}
  2385. Function SetFileInformation(DirHandle:Byte; FilePath:string;
  2386.                             SearchAttrib:Byte;
  2387.                             fileInfo:TEntry):boolean;
  2388. Type Treq=record
  2389.           len          :word;
  2390.           subFunc      :byte;
  2391.           _Fattr,
  2392.           _ExtFattr    :Byte;
  2393.           reserved1    :LongInt; {hi-lo}
  2394.           _crDate      :word;    {hi-lo}
  2395.           _lastAccDate :word;    {hi-lo}
  2396.           _lastUpdTime :Longint;
  2397.           _ownerObjId  :Longint; {hi-lo}
  2398.           _lastArchTime:Longint;
  2399.           reserved2    :array[1..56] of byte;
  2400.           _dirHandle   :Byte;
  2401.           _searchAttr  :byte;
  2402.           _filePath    :string;
  2403.           end;
  2404.      TPreq=^Treq;
  2405. Var DummyDate:Longint;
  2406. Begin
  2407. WITH TPreq(GlobalReqBuf)^
  2408. do begin
  2409.    subFunc:=$10;
  2410.    _Fattr:=Lo(LowLong(fileInfo.Attributes));
  2411.    _ExtFattr:=Hi(LowLong(fileinfo.Attributes));
  2412.    _ownerObjId:=Lswap(fileinfo.OwnerId); {force hi-lo}
  2413.    _dirHandle:=DirHandle;
  2414.    _searchAttr:=SearchAttrib;
  2415.    _filePath:=FilePath;
  2416.    If Dirhandle=0
  2417.     then ConvertPathToVolFormat(_FilePath);
  2418.    UpString(_filePath);
  2419.    NovTime2DosTime(fileinfo.CreationTime,dummyDate);
  2420.    _crDate:=HiLong(dummyDate);
  2421.    NovTime2DosTime(fileinfo.LastAccessTime,dummyDate);
  2422.    _lastAccDate:=HiLong(dummyDate);
  2423.    NovTime2DosTime(fileinfo.ModifyTime,_lastUpdTime);
  2424.    NovTime2DosTime(fileinfo.ArchiveTime,_lastArchTime);
  2425.    len:=82+ord(_filepath[0]);
  2426.    F2SystemCall($17,len+2,0,result);
  2427.    end;
  2428. SetFileInformation:=(result=0);
  2429. { result codes: 00 Success }
  2430. end;
  2431.  
  2432.  
  2433. {F244 [2.1x/3.x]}
  2434. Function EraseFiles(dirHandle, searchAttrib:Byte; filePath:string ):boolean;
  2435. { marks files for deletion / in DOS parlance: delete file, file remains purgable }
  2436. Type Treq=record
  2437.           _dirHandle:Byte;
  2438.           _Sattr:Byte;
  2439.           _filePath:string;
  2440.           end;
  2441.      TPreq=^Treq;
  2442. Begin
  2443. WITH TPreq(GlobalReqBuf)^
  2444. do begin
  2445.    _dirHandle:=dirHandle;
  2446.    _Sattr:=searchAttrib;
  2447.    _filePath:=filePath;
  2448.    F2SystemCall($44,3+ord(_filepath[0]),0,result);
  2449.    end;
  2450. EraseFiles:=(result=0);
  2451. { resultcodes: 00 Success; 98h Volume doesn't exist; 9Bh bad directory handle;
  2452.               9Ch invalid path; FFh no files found error. }
  2453. end;
  2454.  
  2455. {F216/1B [3.0+]}
  2456. Function ScanSalvagableFiles(DirHandle:Byte;
  2457.                       {i/o}  Var EntryId:Longint;
  2458.                       {out}  Var Entry:Tentry   ):boolean;
  2459. { Iterate (with entryId set to -1 at first) until an error $FF occurs }
  2460. Type Treq=record
  2461.           len       :word;
  2462.           subFunc   :byte;
  2463.           _DirHandle:Byte;
  2464.           _EntryId  :Longint; {low_word-hi_word & each word lo-hi }
  2465.           end;
  2466.      Trep=record
  2467.           _EntryId     :Longint;
  2468.           _Entry       :TintEntry;
  2469.           end;
  2470.      TPreq=^Treq;
  2471.      TPrep=^Trep;
  2472. Begin
  2473. WITH TPreq(GlobalReqBuf)^
  2474.  do begin
  2475.     len:=SizeOf(Treq)-2;
  2476.     subFunc:=$1B;
  2477.     _DirHandle:=DirHandle;
  2478.     _EntryId:=EntryId;
  2479.     end;
  2480. F2SystemCall($16,SizeOf(Treq),Sizeof(Trep),result);
  2481. With TPrep(GlobalReplyBuf)^
  2482.  do begin
  2483.     EntryId:=_EntryId; {return next EntryId for iteration}
  2484.                         {low_word-hi_word & each word lo-hi }
  2485.     Convert2ExtEntry(_Entry,Entry);
  2486.     end;
  2487. ScanSalvagableFiles:=(result=0)
  2488. { 98 Volume does not exist  FF No more erased files }
  2489. end;
  2490.  
  2491. {F216/1D  [3.0+]}
  2492. Function PurgeSalvagableFile(DirHandle:Byte;
  2493.                              EntryId:Longint; FileName:string):boolean;
  2494. { either supply an entryId and an empty filename,
  2495.   or supply an entryId of -1 and a filename. Note that the filename
  2496.   may not be unique: there may be more than one old deleted versions
  2497.   of a filename. }
  2498. Type Treq=record
  2499.           len       :word;
  2500.           subFunc   :byte;
  2501.           _DirHandle:Byte;
  2502.           _EntryId  :Longint;   {low_word-hi_word & each word lo-hi }
  2503.           _Name     :string[255];
  2504.           end;
  2505.      TPreq=^Treq;
  2506. Begin
  2507. WITH TPreq(GlobalReqBuf)^
  2508.  do begin
  2509.     subFunc:=$1D;
  2510.     _DirHandle:=DirHandle;
  2511.     _EntryId:=EntryId;
  2512.     _Name:=FileName;
  2513.     UpString(_name);
  2514.     len:=7+ord(_Name[0]);
  2515.     F2SystemCall($16,len+2,0,result);
  2516.     end;
  2517. PurgeSalvagableFile:=(result=0)
  2518. end;
  2519.  
  2520. {F216/1C [3.0+] }
  2521. Function RecoverSalvagableFile(dirHandle:Byte; EntryId:Longint;
  2522.                                OldName,NewName:string):boolean;
  2523. { entryId may be set to -1
  2524.   OldName is the name of the file before it was deleted.
  2525.   NewName is the name to be assigned to the recovered file }
  2526. Type Treq=record
  2527.           len           :word;
  2528.           subFunc       :byte;
  2529.           _DirHandle    :Byte;
  2530.           _EntryId      :Longint;  {low_word-hi_word & each word lo-hi }
  2531.           _OldAndNewName:string[255];
  2532.           end;
  2533.      TPreq=^Treq;
  2534. Begin
  2535. WITH TPreq(GlobalReqBuf)^
  2536.  do begin
  2537.     subFunc:=$1C;
  2538.     _DirHandle:=DirHandle;
  2539.     _EntryId:=EntryId;
  2540.     UpString(OldName);
  2541.     UpString(NewName);
  2542.     _OldAndNewName:=OldName;
  2543.     move(NewName[0],_OldAndNewName[ord(oldname[0])+1],ord(NewName[0])+1);
  2544.     len:=8+ord(oldName[0])+ord(NewName[0]);
  2545.     F2SystemCall($16,len+2,0,result);
  2546.     end;
  2547. RecoverSalvagableFile:=(result=0)
  2548. { 98 Volume does not exist  FF No more erased files }
  2549. end;
  2550.  
  2551.  
  2552. {F216/24 [3.0+]}
  2553. Function SetDirRestriction(DirHandle:Byte; DiskSpaceLimit:Longint):boolean;
  2554. { limit expressed in Blocks. set limit to 0 to lift limit.
  2555.   use a negative number if limit should be equal to 0 }
  2556. Type Treq=record
  2557.           len       :word;
  2558.           subFunc   :byte;
  2559.           _DirHandle:Byte;
  2560.           _Limit    :Longint;
  2561.           end;
  2562.      TPreq=^Treq;
  2563. Begin
  2564. WITH TPreq(GlobalReqBuf)^
  2565.  do begin
  2566.     len:=SizeOf(Treq)-2;
  2567.     subFunc:=$24;
  2568.     _DirHandle:=DirHandle;
  2569.     _Limit:=DiskSpaceLimit;
  2570.     end;
  2571. F2SystemCall($16,SizeOf(Treq),0,result);
  2572. SetDirRestriction:=(result=0)
  2573. end;
  2574.  
  2575.  
  2576. {F216/23 [3.0+]}
  2577. Function ScanDirRestrictions(DirHandle:Byte;
  2578.                            Var NumberOfEntries:Byte;
  2579.                            Var RestrInfo:TdirRestrList):boolean;
  2580. Type Treq=record
  2581.           len:word;
  2582.           subFunc:byte;
  2583.           _DirHandle:Byte;
  2584.           end;
  2585.      Trep=record
  2586.           _Entries:Byte;
  2587.           _Info:TdirRestrList;
  2588.           end;
  2589.      TPreq=^Treq;
  2590.      TPrep=^Trep;
  2591. Begin
  2592. WITH TPreq(GlobalReqBuf)^
  2593.  do begin
  2594.     len:=SizeOf(Treq)-2;
  2595.     subFunc:=$23;
  2596.     _DirHandle:=DirHandle;
  2597.     end;
  2598. F2SystemCall($16,SizeOf(Treq),Sizeof(Trep),result);
  2599. With TPrep(GlobalReplyBuf)^
  2600.  do begin
  2601.     NumberOfEntries:=_Entries;
  2602.     RestrInfo:=_Info;
  2603.     end;
  2604. ScanDirRestrictions:=(result=0)
  2605. end;
  2606.  
  2607.  
  2608. Procedure FixEntryNameFormat(Var s:string);
  2609. Var res:string;
  2610.     p:byte;
  2611. begin
  2612. res:='';
  2613. for p:=1 to ord(s[0])
  2614.  do begin
  2615.     if s[p]='?'
  2616.      then res:=res+#$FF+#$BF
  2617.      else if s[p]='*'
  2618.            then res:=res+#$FF+'*'
  2619.            else res:=res+s[p]
  2620.     end;
  2621. s:=res;
  2622. end;
  2623.  
  2624.  
  2625. {F216/1E [2.15c+]}
  2626. Function ScanDirectoryEntry(DirHandle:Byte; EntryName:string; SearchFlags:Longint;
  2627.                       {i/o} Var EntryId:Longint;
  2628.                       {out} Var Entry:Tentry    ):boolean;
  2629. Type Treq=record
  2630.           len         :word;
  2631.           subFunc     :byte;
  2632.           _DirHandle  :Byte;
  2633.           _SearchFlags:Byte;    { standard: $16 for dirs / $06 for files }
  2634.           _SeqNbr     :Longint; { lo-hi , set to -1 initially }
  2635.           _EntryName  :string;
  2636.           end;
  2637.  
  2638.      Trep=record { len = 84h = 132 dec. }
  2639.           _EntryID      :Longint;    { lo-hi }
  2640.           _Entry        :TintEntry;
  2641.           end;
  2642.      TPreq=^Treq;
  2643.      TPrep=^Trep;
  2644. Begin
  2645. WITH TPreq(GlobalReqBuf)^
  2646.  do begin
  2647.     subFunc:=$1E;
  2648.     _DirHandle:=DirHandle;
  2649.     _SearchFlags:=SearchFlags;
  2650.     _SeqNbr:=EntryId;
  2651.     _EntryName:=EntryName;UpString(_EntryName);
  2652.     FixEntryNameFormat(_EntryName);
  2653.     len:=8+ord(_EntryName[0]);
  2654.     F2SystemCall($16,len+2,Sizeof(Trep),result);
  2655.     end;
  2656. With TPrep(GlobalReplyBuf)^
  2657.  do begin
  2658.     EntryId:=_EntryId; {return next EntryId for iteration}
  2659.     Convert2ExtEntry(_Entry,entry);
  2660.     end;
  2661. ScanDirectoryEntry:=(result=0)
  2662. end;
  2663.  
  2664. {F216/25 [2.15c+] }
  2665. Function SetEntry(DirHandle:Byte;EntryId:Longint;SearchFlags:Byte;
  2666.                   ModFlags:Longint; Entry:Tentry                ):boolean;
  2667. Type Treq=record
  2668.           len       :word;
  2669.           subFunc   :byte;
  2670.           _dirHandle:Byte;
  2671.           _SFlags   :Byte;
  2672.           _EntryId  :Longint; {lo-hi}
  2673.           _ModFlags :Longint; {lo-hi}
  2674.           _Entry    :TintEntry;
  2675.           end;
  2676.      TPreq=^Treq;
  2677. Begin
  2678. WITH TPreq(GlobalReqBuf)^
  2679.  do begin
  2680.     len:=SizeOf(Treq)-2;
  2681.     subFunc:=$25;
  2682.     _dirHandle:=DirHandle;
  2683.     _EntryId:=EntryId;
  2684.     _ModFlags:=ModFlags;
  2685.     Convert2IntEntry(Entry,_Entry);
  2686.     end;
  2687. F2SystemCall($16,SizeOf(Treq),0,result);
  2688. SetEntry:=(result=0)
  2689. end;
  2690.  
  2691. {------------------ Secondary Functions ----------------------------}
  2692.  
  2693. Function IsFileShareable(Path : String):boolean;
  2694.  
  2695. var F: File;
  2696.     FAttr : Word;
  2697.  
  2698. begin
  2699.  { Assign(F, Path);
  2700.   GetFAttr(F, FAttr);
  2701.   result:=DOSerror; }
  2702.   IsFileShareable:=(result=0) and ((FAttr and $80)>0)
  2703. end;
  2704.  
  2705. function FlagFileShareable(Path : String) : Boolean;
  2706. { when the file could NOT be made shareable, false is returned as the
  2707.   function result, a doserror# is returned as the result code. }
  2708. var  F : File;
  2709.      Attr : Word;
  2710.      ErrCode : word;
  2711.      Share            : Boolean;
  2712. begin
  2713. if NOT IsFileShareable(Path) { Share: is it sharable? }
  2714.  then begin
  2715.       Assign(F,Path);
  2716.       {SetFAttr(F,Attr or A_SHAREABLE);  OR existing atrib. with SHARE bit }
  2717.       {Result := DOSError;}
  2718.       end;
  2719. FlagFileShareable := (Result=0);
  2720. end;
  2721.  
  2722.  
  2723. Function GetFileHandle(Var f):word;
  2724. begin
  2725. {GetFileHandle:=filerec(f).handle;}
  2726. end;
  2727.  
  2728. {------===================-- Trustee/Max. Rights masks --=================--}
  2729.  
  2730.  
  2731. {F216/27  [3.0+]}
  2732. Function SetTrustee(DirHandle:Byte;DirPath:string;
  2733.                     TrusteeObjectID:Longint;
  2734.                     RightsMask:Word               ):boolean;
  2735. Type Treq=record
  2736.           len       :word;
  2737.           subFunc   :byte;
  2738.           _DirHandle:byte;
  2739.           _ObjId    :Longint;  { hi-lo }
  2740.           _Rights   :Word;     { lo-hi }
  2741.           _DirPath  :string;
  2742.           end;
  2743.      TPreq=^Treq;
  2744. Begin
  2745. WITH TPreq(GlobalReqBuf)^
  2746.  do begin
  2747.     subFunc:=$27;
  2748.     _DirHandle:=DirHandle;
  2749.     if DirHandle=0
  2750.      then ConvertPathToVolFormat(DirPath);
  2751.     _DirPath:=DirPath;UpString(_DirPath);
  2752.     _ObjId:=Lswap(TrusteeObjectId);
  2753.     _Rights:=RightsMask;
  2754.     len:=9+ord(_DirPath[0]);
  2755.     F2SystemCall($16,len+2,0,result);
  2756.     end;
  2757. SetTrustee:=(result=0)
  2758. { Possible resultcodes: 8C No modify privileges;
  2759.   98 Volume doesn't exist; 9B Bad directory handle
  2760.   9C Invalid path; FC No such bindery object }
  2761. end;
  2762.  
  2763.  
  2764. {F216/2B [3.0+]}
  2765. Function DeleteTrustee(DirHandle:Byte;DirPath:String;
  2766.                        TrusteeObjectId:Longint):boolean;
  2767. { If DirHandle equals 0, DirPath should be according to the
  2768.   VOL:\path format. All other path formats will result in
  2769.   an resultcode of 98h (No such volume) }
  2770. Type Treq=record
  2771.           len       :word;
  2772.           subFunc   :byte;
  2773.           _DirHandle:byte;
  2774.           _ObjId    :Longint;  { hi-lo }
  2775.           _Unused   :Byte;
  2776.           _DirPath  :string;
  2777.           end;
  2778.      TPreq=^Treq;
  2779. Begin
  2780. WITH TPreq(GlobalReqBuf)^
  2781.  do begin
  2782.     subFunc:=$2B;
  2783.     _DirHandle:=DirHandle;
  2784.     if DirHandle=0
  2785.      then ConvertPathToVolFormat(DirPath);
  2786.     _DirPath:=DirPath;UpString(_DirPath);
  2787.     _ObjId:=Lswap(TrusteeObjectId);
  2788.     _Unused:=0;
  2789.     len:=8+ord(_DirPath[0]);
  2790.     F2SystemCall($16,len+2,0,result);
  2791.     end;
  2792. DeleteTrustee:=(result=0);
  2793. { Possible resultcodes: 98 Volume doesn't exist
  2794.   9B Bad directory handle; 9C Invalid path
  2795.   FE no such trustee  }
  2796. end;
  2797.  
  2798.  
  2799. {F216/2A [3.0+]}
  2800. function GetEffectiveRights(DirHandle:Byte;DirPath:String;
  2801.                         var Rights:Word) : Boolean;
  2802. { returns the requesting workstation's effective directory rights }
  2803. Type Treq=record
  2804.           Len         : word;
  2805.           SubF        : Byte;
  2806.           _DirHandle  : Byte;
  2807.           _DirName    : String;
  2808.           end;
  2809.      TRep=record
  2810.           _RightsMask : Word;
  2811.           end;
  2812.      TPreq=^Treq;
  2813.      TPrep=^Trep;
  2814. begin
  2815. with TPreq(GlobalReqBuf)^
  2816.  do begin
  2817.     SubF        := $2A;
  2818.     _DirHandle  := DirHandle;
  2819.     if DirHandle=0
  2820.      then ConvertPathToVolFormat(DirPath);
  2821.     _DirName    := DirPath;UpString(_DirName);
  2822.     Len         := 3+ord(DirPath[0]);
  2823.     F2SystemCall($16,len+2,SizeOf(Trep),result);
  2824.     end;
  2825. with TPrep(GlobalReplyBuf)^
  2826.  do Rights:=_RightsMask;
  2827. GetEffectiveRights:=(Result=0);
  2828. { return byte
  2829.   00h  - Success
  2830.   98h  - Volume Does Not Exist
  2831.   9Bh  - Bad Directory Handle  }
  2832. end;
  2833.  
  2834.  
  2835. {F216/04 [2.15c+]}
  2836. Function ModifyMaximumRightsMask(DirHandle:Byte;DirPath:string;
  2837.                                  RevokeRightsMask,GrantRightsMask:Word):boolean;
  2838. Type Treq=record
  2839.           len:word;
  2840.           subFunc:byte;
  2841.           _DirHandle:Byte;
  2842.           _GrantRM,
  2843.           _RevokeRM:Byte;
  2844.           _DirPath:String;
  2845.           end;
  2846.      Trep=record
  2847.           _EffectiveRightsMask:Byte;
  2848.           end;
  2849.      TPreq=^Treq;
  2850.      TPrep=^Trep;
  2851. Begin
  2852. WITH TPreq(GlobalReqBuf)^
  2853.  do begin
  2854.     len:=5+ord(DirPath[0]);
  2855.     subFunc:=$04;
  2856.     _DirHandle:=DirHandle;
  2857.     if DirHandle=0
  2858.      then ConvertPathToVolFormat(DirPath);
  2859.     _GrantRM:=MapV3RightsToV2(GrantRightsMask);
  2860.     _RevokeRM:=MapV3RightsToV2(RevokeRightsMask);
  2861.     _DirPath:=DirPath;
  2862.     F2SystemCall($16,len+2,Sizeof(Trep),result);
  2863.     end;
  2864. {With TPrep(GlobalReplyBuf)^
  2865.  do begin
  2866.     --- nothing is done with the returned value---
  2867.     end;}
  2868. ModifyMaximumRightsMask:=(result=0)
  2869. { result codes: 8C No modify privileges; 98 Volume dosn't exist;
  2870.                 9C Invalid path }
  2871. end;
  2872.  
  2873.  
  2874.  
  2875. {F217/47 [2.15c+]}
  2876. Function ScanBinderyObjectTrusteePaths(TrusteeObjectId:Longint;
  2877.                                        VolumeNumber:Byte;
  2878.                              {i/o} Var SequenceNumber:word;
  2879.                              {out} Var AccessMask:Word;
  2880.                                    Var Path:string        ):boolean;
  2881. { You must be supervisor (-equivalent) or the TrusteeObject itself
  2882.   to use this function.
  2883.   Initially, sequencenumber should be set to 0. }
  2884. Type Treq=record
  2885.           len    :word;
  2886.           subFunc:byte;
  2887.           _VolNbr:Byte;
  2888.           _SeqNbr:word; {hi-lo}
  2889.           _ObjId :Longint; {hi-lo}
  2890.           end;
  2891.      Trep=record
  2892.           _NextSeqNbr:Word; {hi-lo}
  2893.           _ObjId     :Longint; {hi-lo}
  2894.           _AccMask   :byte;
  2895.           _Path      :string;
  2896.           end;
  2897.      TPreq=^Treq;
  2898.      TPrep=^Trep;
  2899. Begin
  2900. WITH TPreq(GlobalReqBuf)^
  2901.  do begin
  2902.     len:=SizeOf(Treq)-2;
  2903.     subFunc:=$47;
  2904.     _VolNbr:=VolumeNumber;
  2905.     _SeqNbr:=swap(SequenceNumber);
  2906.     _ObjId:=Lswap(TrusteeObjectId);
  2907.     end;
  2908. F2SystemCall($17,SizeOf(Treq),Sizeof(Trep),result);
  2909. With TPrep(GlobalReplyBuf)^
  2910.  do begin
  2911.     SequenceNumber:=Lswap(_NextSeqNbr);
  2912.     Accessmask:=_AccMask; {MapV2RightsToV3(_accMask);}
  2913.     Path:=_Path;
  2914.     end;
  2915. ScanBinderyObjectTrusteePaths:=(result=0)
  2916. { resultcodes:
  2917.   $96 Server out of memory; $F0 Wildcard not allowed;
  2918.   $F1 Invalid bindery security; $FC No such object;
  2919.   $FE Server bindery locked; $FF Bindery failure }
  2920. end;
  2921.  
  2922. {F216/26 [3.0+]}
  2923. Function ScanEntryForTrustees(DirHandle:Byte;DirPath:String;
  2924.                     {i/o} Var SequenceNumber:Byte;
  2925.                     {out} Var TrusteeInfo: TtrusteeInformation):boolean;
  2926. { Set SequenceNumber to 0 initially,
  2927.   iterate until error $9C (no more trustees) is returned }
  2928. { see GETTR in the XFILE archive for an example }
  2929. Type Treq=record
  2930.           len:word;
  2931.           subFunc:byte;
  2932.           _DirHandle:Byte;
  2933.           _SeqNbr:Byte;
  2934.           _DirPath:String;
  2935.           end;
  2936.      Trep=record
  2937.           _Info:TtrusteeInformation;
  2938.           end;
  2939.      TPreq=^Treq;
  2940.      TPrep=^Trep;
  2941. Var t:Byte;
  2942. Begin
  2943. WITH TPreq(GlobalReqBuf)^
  2944.  do begin
  2945.     len:=4+ord(DirPath[0]);
  2946.     subFunc:=$26;
  2947.     _DirHandle:=DirHandle;
  2948.     if DirHandle=0
  2949.      then ConvertPathToVolFormat(DirPath);
  2950.     _SeqNbr:=SequenceNumber;
  2951.     _DirPath:=DirPath;UpString(_DirPath);
  2952.     F2SystemCall($16,len+2,Sizeof(Trep),result);
  2953.     end;
  2954. With TPrep(GlobalReplyBuf)^
  2955.  do begin
  2956.     inc(SequenceNumber);
  2957.     TrusteeInfo.NumberOfTrustees:=_Info.NumberOfTrustees;
  2958.     for t:=1 to 20
  2959.      do begin
  2960.         TrusteeInfo.TrusteeId[t]:=Lswap(_Info.TrusteeId[t]);
  2961.         TrusteeInfo.TrusteeRights[t]:=_Info.TrusteeRights[t];
  2962.         end;
  2963.     end;
  2964. ScanEntryForTrustees:=(result=0)
  2965. { resultcodes:
  2966.   $9C No more trustees }
  2967. end;
  2968.  
  2969.  
  2970.  
  2971.  
  2972. {F2  [2.15c+]
  2973. Function (   ):boolean;
  2974. Type Treq=record
  2975.           len:word;
  2976.           subFunc:byte;
  2977.  
  2978.           end;
  2979.      Trep=record
  2980.  
  2981.           end;
  2982.      TPreq=^Treq;
  2983.      TPrep=^Trep;
  2984. Begin
  2985. WITH TPreq(GlobalReqBuf)^
  2986.  do begin
  2987.     len:=SizeOf(Treq)-2;
  2988.     subFunc:=$
  2989.  
  2990.     end;
  2991. F2SystemCall($ ,SizeOf(Treq),Sizeof(Trep),result);
  2992. With TPrep(GlobalReplyBuf)^
  2993.  do begin
  2994.  
  2995.     end;
  2996.  :=(result=0)
  2997. end; }
  2998.  
  2999. end.